2013-06-13 20 views
9

Próbuję wprowadzić alias dla wyliczenia w jednym obszarze nazw do innego obszaru nazw. Chociaż mogę zadeklarować zmienną typu alias, kompilator (gcc 4.1.2) nie rozpozna żadnej z wartości wyliczenia.C++ typedefs i enums

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; 
} 

Błąd kompilatora jest

test.cc:12: error: 'One' nie jest członkiem 'B'.

+0

spróbuj użyć A :: a as b; wewnątrz przestrzeni nazw B (lub coś w tym stylu). (To dlatego jest to komentarz, a nie odpowiedź.) – jmucchiello

+4

To dlatego, że 'Jeden' ​​jest ** nie ** członkiem' B' ... –

+0

To jest naprawdę stary kompilator. Czy naprawdę potrzebujesz korzystać z tej wersji? – stefan

Odpowiedz

7

podczas gdy typ enum jest dostępny w B przez b, wartości nie są i muszą być podane w sposób wyraźny:

namespace B { 
    typedef A::a b; 
    using A::One; 
} 

Nie sądzę, istnieje sposób, aby doprowadzić je wszystkie bez oddzielnych using sprawozdania dla każdego, chyba że wykonasz using namespace A; lub umieść enum w inline namespace i będziesz miał do tego instrukcję using. Ta ostatnia może być lepsza, jeśli martwisz się wprowadzeniem całych A i nadal chcesz użyć wartości wyliczeniowych tylko z A::value. Oto przykład:

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 

Należy pamiętać, że wbudowane przestrzenie nazw zostały wprowadzone w C++ 11, do którego GCC 4.1.2 nie ma wsparcia. Jeśli możesz, zdecydowanie zalecam uaktualnienie. Najnowsza stabilna wersja to 4.8.1.

0

C++ przed C++ 11 nie oferuje żadnego (prostego) rozwiązania dla tego problemu. W C++ 11, może zadeklarować enum scoped, używając następującej składni:

enum struct a { /* .... */ }; // the class keyword may also be used 

Efekt jest, aby rachmistrzowie (stałe) scoped wewnątrz samego typu enum, tj. notacja dostępu do stałych z a na przykład staje się a::One. Ponieważ teraz należą one do typu wyliczeniowego, a nie do przestrzeni nazw, można je łatwo importować wraz z wyliczeniem do innego obszaru nazw za pomocą typedef. Należy jednak pamiętać, że wartości wyliczone na podstawie zakresu mogą nie być promowane do int tak łatwo, jak w przypadku zwykłych wyliczeń.

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; 
}