2011-07-01 7 views
2

可能性の重複別の内部の1つの名前空間を列挙し、使用イストをtypdefする方法:
How do you import an enum into a different namespace in C++?は、C++

方法次の列挙型の名前空間の問題が解決されてことができますか?

namespace A { 
    typedef enum ABar { a, b }; 

    void foo(ABar xx) {} 
} 

namespace B { 
    typedef enum A::ABar BBar; 

     void foo(BBar xx) { A::foo(xx); } 
} 

int main() { 
    B::foo(B::a); // 'a' : is not a member of 'B' 
        // 'a' : undeclared identifier 
} 

答えて

2

列挙型をtypedefできません。あなたはそれを使用することができます。

namespace B { 
    using A::ABar; 
} 

EDIT作品ここでは例を修正する

、:

namespace A { 
    enum ABar { a, b }; 

    void foo(ABar xx) {} 
} 
namespace B { 
    using A::ABar;  // 'ABar' : is injected into namespace 'B' 
    using A::a;   // 'a' : is injected into namespace 'B' 

     void foo(ABar xx) { A::foo(xx); } 
} 
int main() { 
    B::foo(B::a); 
} 

をしかし、CygnusX1とDavidように指摘し、上記の名前空間Bを汚染されましたこのようにする方が良いです:

namespace A { 
    enum ABar { a, b }; 

    void foo(ABar xx) {} 
} 
namespace B { 
     void foo(A::ABar xx) { A::foo(xx); } 
} 
int main() { 
    B::foo(A::a); 
} 

あり、それをtypedefのために、また、第三の選択肢ですが、適切に:

namespace B { 
    typedef A::ABar BBar; 

     void foo(BBar xx) { A::foo(xx); } 
} 

あなたはまだこれを行うことはできません。

B::foo(B::a); // 'a' : is not a member of 'B' 
       // 'a' : undeclared identifier 

BBARは、::、Abarの可単なる別名であるため。

+0

申し訳ありませんが、私は実際の問題を表しているので、例を変更しました... – DrFroid

+0

実際に試しましたか?私の最初の推測はこれでしたが、これは機能しません。 –

+0

問題は、他の列挙型の1つを反映する独自の列挙型を定義する必要があるということです。 – DrFroid

8

型をtypedefしているときに、その名前空間で定義されているシンボルはインポートしません。したがって、あなたは書くことができます:

このシンボルが存在しないため、B::aにアクセスすることはできません。

部分walkaroundと、私の意見では、コードをよりきれいにする方法、もう少し長い書き込むこともあるが、独自の構造体の中に例えば、すべての列挙型をパックすることです:

struct ABar { 
    enum Type {a, b}; 
}; 

typedef ABar BBar; 

int main() { 
    ABar::Type var=ABar::a; 
    BBar::Type var2=BBar::a; 
} 

それでも必要な場合は、ABarを名前空間にパックし、通常は別の名前空間にtypedefすることもできます。

+0

問題を参照してください。列挙型を独自のクラスにパックすることは、ブースト列挙型なので、オプションではありません;-) – DrFroid

+0

それはどのようなブースト列挙ですか? – CygnusX1

+0

boost :: date_time :: weekdays/months_of_yearとboost :: date_time :: nth_kday_of_month < Date_t > :: week_num – DrFroid

4

問題は、列挙型の宣言が型を作成するだけでなく、指定された値で列挙型識別子を宣言することです。 typedefを実行すると、型へのローカルエイリアスしか作成されませんが、値は新しい名前空間に持ち込まれません。つまり、コンパイラにはB::BBarが表示され、typedefを使ってA::ABarを参照していることがわかります。しかし、B::aを処理している間は、それを参照するB名前空間には何もありません。

これが機能するには、abを新しい名前空間に持ち込む必要があります。これはタイプではないため、typedefによって行われません。とにかく、それはのような達成可能である:それは非常に急速にメンテナンスの問題になるよう

namespace A { 
    enum ABar { 
     a, b 
    }; 
} 
namespace B { 
    typedef ::A::ABar BBar; 
    using ::A::a; 
    using ::A::b; 
} 

私はあなたがオリジナルのものにそれぞれ変更して、両方の名前空間を更新するために覚えておく必要があります(、それをやってお勧めしません

@ CygnusX1で提案されている回避策は、実際には良い選択です.C++ 0xコンパイラを使用している場合は、列挙された値にアクセスするのと同様のイディオムが使用できます列挙型を介して:

namespace A { 
    enum ABar { a,b }; 
} 
namespace B { 
    typedef A::ABar BBar; 
} 
int main() { 
    std::cout << B::BBar::a << std::endl; // extra enum qualification 
} 
+0

ok、thnaksです。これは私に多くの助けになります。貧弱なことは、vc 9はC++ 0x互換ではありません。なぜなら、これは私にとって最高のソリューションのように見えるからです。しかし、その問題を解決するCygnusの方法は、私のためにも機能します。 – DrFroid