簡體   English   中英

c ++ typedef另一個類的枚舉?

[英]c++ typedef another class's enum?

所以這是我的問題:

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我會收到一個非標准的警告。 有沒有辦法做這樣的事情?

我認為A應該是命名空間而不是結構。

將枚舉放在全局范圍內太暴露了,將它們放在一個類中會引入不受歡迎的依賴。 對於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;

希望有更好的方法,但到目前為止,這是我找到的唯一解決方案。

似乎沒有一個簡單的解決方案。 也困擾我。 如果允許更改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:再次刪除第二個解決方案,不能像我想象的那樣工作。

我過去也遇到過同樣的問題,這就是我修復它的方法。 我希望能夠在編譯時切換庫的實現。 其中一個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庫。

我有同樣的問題,我使用這個解決方案,而不是使用多余的命名空間。 它使枚舉安全地隱藏在類及其顯式用戶中。

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

為什么你甚至在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的實例來調用該方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM