Jim Russell
Jim Russell

Reputation: 99

C++ typedefs and enums

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

Answers (2)

didierc
didierc

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

Qaz
Qaz

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

Related Questions