所以这是我的问题:
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
,我会收到一个非标准的警告。有没有办法做这样的事情?
答案 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的实例来调用方法。