c ++ typedef另一个类的枚举?

时间:2009-05-23 18:10:39

标签: c++ enums typedef

所以这是我的问题:

struct A
{
    enum A_enum
    {
        E0,
        E1,
        E2
    };
};

struct B
{
    typedef A::A_enum B_enum;
    bool test(B_enum val)
    {
        return (val == E1); // error: "E1" undeclared identifier
    }
};

我特别不想说A::E1。如果我尝试B_enum::E1,我会收到一个非标准的警告。有没有办法做这样的事情?

6 个答案:

答案 0 :(得分:3)

我认为A应该是命名空间而不是结构。

答案 1 :(得分:2)

将枚举放在全局范围中太暴露了,将它们放在一个类中会引入不需要的依赖。对于enum没有紧密链接到类,这是我使用的:

#define CLEANENUMS_BEGIN(name) namespace name { typedef enum {
#define CLEANENUMS_END(name) } internal_ ## name ## _e;} typedef name::internal_ ## name ## _e name ## _e;

然后你可以在全球范围内使用:

CLEANENUMS_BEGIN(myEnum)
    horizontal,
    vertical,
CLEANENUMS_END(myEnum)

这或多或少模仿处理枚举范围的C#方式。预处理器将生成此代码:

namespace myEnum
{
    enum internal_myEnum_e
    {
        horizontal,
        vertical,
    }
}
typedef internal_myEnum_e myEnum_e;

然后将给定的枚举引用为

myEnum_e val = myEnum::horizontal;

希望有更好的方法可以做到这一点,但到目前为止,这是我找到的唯一解决方案。

答案 2 :(得分:0)

过去我遇到过同样的问题,这就是我修复它的方法。 我希望能够在编译时切换库的实现。 其中一个lib使用这样的代码:

namespace Lib1 
{
  enum LibEnum { One, Two, Three };
  [...]
  void someFunc(LibEnum val);
}

在我的代码中,我想从用户体验中隐藏库实现(因此我的代码的用户永远不会看到我在内部使用的lib):

解决方案1:

namespace MyCode 
{
  // Example to avoid copying a function from Lib1 here
  typedef Lib1::someFunc aFunctionImUsing;

  // This doesn't work
  // typedef LibEnum MyEnum; 
  // As such code doesn't compile:
  // aFunctionImUsing(One); // Error unknown identifier One
  // But this did:
  struct Type
  {
     enum MyType { One = Lib1::One, Two = Lib1::Two, Three = Lib1::Three };
  }
  static inline Lib1::LibEnum as(Type::MyType t) { return (Lib1::LibEnum)t; }

  // Now code like this compiles:
  aFunctionImUsing(as(Type::One));
  // This one doesn't:
  // aFunctionImUsing(Type::One); // Can't convert from Type::MyType to Lib1::LibEnum

  [...]
}

解决方案2:

namespace MyCode 
{
  struct Type
  {
     enum MyType { One = Lib1::One, Two = Lib1::Two, Three = Lib1::Three };
  }

  // If you don't care about polluting your namespace with numerous wrapper 
  // you can write this instead of typedef someFunc:
  static inline void myFunc(Type::MyType t) { return Lib1::someFunc((Lib1::LibEnum)t); }

  // This one does:
  myFunc(Type::One); 
  [...]
}

上面的代码片段是2个问题。第一个问题是你必须复制&将枚举粘贴到命名空间内(但在find& replace中使用简单的正则表达式,你就完成了)。 第二个问题是你的用户必须使用“as”方法,这意味着它不是直截了当的,或者你必须使用第二个解决方案包装方法/函数。

无论如何,由于无法在命名空间中注入枚举,因此该解决方案是您可以做的最好的解决方案。请注意,您的代码用户甚至不知道您在示例代码中使用了Lib1库。

答案 3 :(得分:0)

我有同样的问题,我使用这个解决方案,而不是使用多余的命名空间。它使枚举安全地隐藏在类及其显式用户中。

class TreeWindow abstract {
public:
  enum CheckState { On, Off, Partial }
};

class TreeControl abstract {
public:
  class ItemChecked abstract: public TreeWindow { // this is the hack needed
  public:
    using TreeWindow::CheckState;
  };

  void func(ItemChecked::CheckState);
};

TreeControl& tree = ...
tree.func(TreeControl::ItemChecked::Partial);

答案 4 :(得分:0)

似乎没有一个简单的解决方案。也困扰我。 如果允许更改A,则如果不需要将枚举内容发送到A外的作用域,则可以使用不依赖于名称空间的解决方案。与使用命名空间相反,A和A_Enum都可以是嵌套类。

struct A_Enum
{
    enum A_enum
    {
        E0,
        E1,
        E2
    };
};

struct A : public A_Enum
{
    using A_Enum::A_enum;
};

struct B : public::A_Enum
{
    using A_Enum::A_enum; // original enum name
    bool testA(A_enum val) { return (val == E1); }
};

EDIT2:再次删除了第二个解决方案,但没有像我想的那样工作。

答案 5 :(得分:-2)

为什么你甚至在struct B中有测试方法?我认为这没有任何意义。

通过定义结构A并在其中定义枚举,你或多或少地说“这里是结构A范围内的枚举”,这与说“如果你想使用这个枚举,你必须参考结构A“。

将枚举放在命名空间内并不能解决您的问题。因为您将遇到相同的范围问题(C4482)

我认为你的事情太复杂了。你怎么看待这个?

struct A
{
    enum A_enum
    {
        E0,
        E1,
        E2
    };

    static bool test(A_enum val)
    {
        return (val == E1);
    }
};


int main()
{
    assert(A::test(A::E1));
    return 0;
}

请注意,A :: test()是静态的。应该是因为你没有在struct状态下运行。因为它是静态的,所以你不需要A的实例来调用方法。