[英]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.