开发者

Conflicting enums

What happens if two different libs define the same enum and I need to use both libs in the same project?

enum Month {January=0, February, ..., December}

Thank you.

P.S. It is C. No namespaces. I won't be able to keep them separated. Need some workaround.

What it the enum linkage开发者_运维技巧? Internal or external? C libs used in C++ project. C++ tag applies.


C libs used in C++ project. C++ tag applies

Since they're used in C++ projects, then you can use namespace when including them in C++ code as:

// C files
//libone.h 
enum Month {January=0, February, ..., December}

//libtwo.h
enum Month {January=0, February, ..., December}

///////////////////////////////////////////////////////////////////
//C++ files

//lib.hpp
namespace LibOne 
{
     #include "libone.h"
}
namespace LibTwo 
{
     #include "libtwo.h"
}

//Usage in C++
LibOne::Month m1 = LibOne::January;
LibTwo::Month m2 = LibTwo::January;


Ultimate magic evil wizard workaround: if namespaces don't help (for whatever reason), and you absolutely can't avoid including both definitions in the same file, use a macro:

#define Month File_A_Month
#include "file_a.h"
#define Month File_B_Month
#include "file_b.h"
#undef Month

In the file, never use Month, only File_A_Month or File_B_Month. I'm not certain of the standards-correctness of this practice.

You might have to define all the enum members similarly to prevent clashes, and you probably want to put this evil hackery in a file called files_a_and_b.h. Of course, in your case the definitions are identical, so you shouldn't need to resort to this, but I'm leaving this answer here for less fortunate posterity.


Neither the enum itself nor the enumeration constants are objects, so they don't have any linkage at all - in this respect, they're like struct tags or typedef names.

This means that you have two workarounds:

  • Ensure that the conflicting headers are never, directly or indirectly, #included in the same translation unit (.c file); or
  • Launder one or both of the headers to change the conflicting names.

The header laundering can be done either by creating a private copy of the header with the names changed, or using the preprocessor as in Chris Lutz's answer.


Ideally, the two are in different namespaces.

Otherwise, you may be able to avoid including both definitions in a single compile unit.

EDIT: Okay, you're in C, so you don't have namespaces, and it sounds like you want to reference both definitions in the same compile unit. Next steps:

  • Do they have exactly the same definition?
  • Do you have any influence on the names in either of the libraries?
  • Are you sure you can't hide references to one of them in a different compile unit?


Quote: I am writing C++ API and the same enum is already defined in my lib's namespace.

So one of these enums is inside the namespace of your library? Then you should not have a problem. The C library you are using is in the global namespace, your library has its own namespace, and as long as you do the Right Thing, the two will never collide. The following is perfectly valid, I believe:

extern "C" {
  #include "foo.h"
  // enum Month { January, February, December };
}

namespace mylib {
  enum Month { Chaos, Discord, Confusion, Bureaucracy, Aftermath };

  Month convert(::Month c_month);
}

void foo() {
  ::Month month = December;
  mylib::Month result = mylib::convert(month);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜