Reputation: 99
I am trying to introduce an alias for an enum in one namespace into another namespace. While I can declare a variable of the aliased type, the compiler (gcc 4.1.2) will not recognize any of the enumeration's values.
namespace A
{
enum a { One = 1, Two = 2 };
}
namespace B
{
typedef enum A::a b;
};
A::a a_value = A::One; // Pretty standard
B::b b_value = B::One; // Does not work
B::b c_value = A::One; // Clearly B is a typedef for A
int main (int argc, const char *argv[])
{
return 0;
}
The compiler error is
test.cc:12: error: 'One' is not a member of 'B'.
Upvotes: 9
Views: 771
Reputation: 14750
C++ prior to C++11 does not offer any (simple) solution for that problem. In C++11, you may declare the enum scoped, using the following syntax:
enum struct a { /* .... */ }; // the class keyword may also be used
The effect is to make enumerators (the constants) scoped within the enum type itself, ie. the notation to access the constants of a
becomes a::One
for instance. Because these now belong to the enum type, and not the namespace, you may easily import them along with the enum into another namespace with a typedef. Note however that scoped enum values may not be promoted to int
as easily as with regular enums.
namespace A {
enum class a { One = 1, Two = 2 };
}
namespace B {
typedef A::a b;
}
A::a a_value = A::One;
B::b b_value = B::One; // Now this works
B::b c_value = A::One; // Clearly B is still a typedef for A
int main (int argc, const char *argv[]) {
return 0;
}
Upvotes: 0
Reputation: 61970
While the enum type is accessible in B
through b
, the values are not and must be brought in explicitly:
namespace B {
typedef A::a b;
using A::One;
}
I don't think there's a way to bring them all in without separate using
statements for each unless you do using namespace A;
or put the enum in an inline namespace and have a using statement for that. The latter might be preferable if you're worried about bringing in all of A
and would still like to use the enum values with just A::value
. Here's an example:
namespace A
{
inline namespace en {
enum a { One = 1, Two = 2 };
}
enum c {Three};
}
namespace B
{
using namespace A::en;
typedef A::a b;
}
A::a a_value = A::One; // works; things in en are still visible in A
B::b b_value = B::One; // works; en was brought into B
B::b c_value = A::One; // works
A::c meh = B::Three; //fails; only en was brought into B
Be aware that inline namespaces were introduced in C++11, which GCC 4.1.2 has no support for. If you can, I would strongly recommend upgrading. The latest stable release is 4.8.1.
Upvotes: 7