如何在另一个命名空间中键入一个命名空间的枚举并使用ist c ++

时间:2011-07-01 07:55:41

标签: c++ enums namespaces

  

可能重复:
  How do you import an enum into a different namespace in 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
}

3 个答案:

答案 0 :(得分:8)

在键入类型时,不会导入该命名空间中定义的符号。所以,虽然你可以写:

int main() {
    B::BBar enumVariable=A::a;
}

由于此符号不存在,您无法访问B::a

部分漫游,在我看来,一种使代码更干净的方法,尽管编写时间更长,但是将每个枚举打包到它自己的结构中,例如:

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

typedef ABar BBar;

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

如果你仍然需要它,你将能够将ABar打包到命名空间中,并且通常也在另一个命名空间中输入typedef。

答案 1 :(得分:4)

问题是枚举的声明不仅创建了类型,而且还声明了具有给定值的枚举标识符。当您执行typedef时,您只是为该类型创建一个本地别名,但这些值不会被带到新的命名空间。也就是说,编译器将看到B::BBar,并且它将通过您引用A::ABar的typedef来了解。但是在处理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
}

答案 2 :(得分:2)

您无法输入定义枚举。你可以使用它:

namespace B {
   using A::ABar;
}

修改

以下是修改后的示例:

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

还有第三个选项,可以键入它,但是正确:

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只是A :: ABar的别名。