2013-06-13 2 views
9

J'essaie d'introduire un alias pour une énumération dans un espace de noms dans un autre espace de noms. Bien que je puisse déclarer une variable du type aliasé, le compilateur (gcc 4.1.2) ne reconnaîtra aucune des valeurs de l'énumération.Typedefs et enums C++

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

L'erreur du compilateur est

test.cc:12: Erreur: 'One' est pas un membre de 'B'.

+0

essayez d'utiliser A :: a comme b; inside namespace B (Ou quelque chose comme ça). (C'est pourquoi c'est un commentaire, et non une réponse.) – jmucchiello

+4

C'est parce que 'One' n'est ** pas ** un membre de' B' ... –

+0

C'est un très vieux compilateur. Avez-vous vraiment besoin d'utiliser cette version? – stefan

Répondre

7

Bien que le type enum est accessible à B par b, les valeurs ne sont pas et doivent être traduits en explicitement:

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

Je ne pense pas qu'il y ait un moyen de les mettre tous dans sans using séparés déclarations pour chaque sauf si vous faites using namespace A; ou mettez l'enum dans un espace de noms en ligne et avez une instruction using pour cela. Ce dernier peut être préférable si vous êtes préoccupé par l'introduction de tous A et que vous souhaitez toujours utiliser les valeurs enum avec juste A::value. Voici un exemple:

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 

Sachez que les espaces de noms inline ont été introduits en C++ 11, GCC 4.1.2 n'a pas de support pour. Si vous le pouvez, je recommande fortement la mise à niveau. La dernière version stable est 4.8.1.

0

C++ avant C++ 11 n'offre aucune solution (simple) pour ce problème. En C++ 11, vous pouvez déclarer l'ENUM scope, en utilisant la syntaxe suivante:

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

L'effet est de faire les agents recenseurs (les constantes) scope dans le type ENUM lui-même, à savoir. la notation pour accéder aux constantes de a devient a::One par exemple. Puisque ceux-ci appartiennent maintenant au type enum, et non à l'espace de noms, vous pouvez facilement les importer avec l'énumération dans un autre espace de noms avec un typedef. Notez toutefois que les valeurs enum scoped ne peuvent pas être promues à int aussi facilement qu'avec des énumérations régulières.

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