我有一个包装枚举的类,便于打印,序列化等。
我希望能够在switch语句中使用它作为传统的枚举,因此我使用了int()overloader直到gcc-4.3。但是我的代码现在用 gcc-4.5.1 打破了。
enum E { consta, constb };
class Wrap {
private:
E e;
public:
operator E() { return e;}
operator E() const { return e;}
operator int() const { return e;}
Wrap(E a) : e(a) { }
};
int main() {
Wrap x(constb);
x = consta;
switch (x) { /* Error here */
case consta: // ..
case constb: // ..
}
return 0;
}
编译器错误是:
错误:来自'Wrap'的模糊默认类型转换
错误:候选转换包括'Wrap :: operator E()const'和'Wrap :: operator int()const'
这是库的一部分,我希望代码可以在所有版本上运行,因此删除int overloader不是一个选项。
答案 0 :(得分:0)
您可以使用static_cast
:
switch(static_cast<E>(x))
另一个选择是创建一个或多个转换运算符explicit
- 这将通过限制编译器的选项来解决歧义。
但是,explicit
转换运算符仅适用于编译器不支持的C ++ 0x。
答案 1 :(得分:0)
将行更改为
switch ((E)x) {
枚举器和整数在编译器中非常相似(并且可能在内存中相同),因此这两者都令人困惑。如果您专门投射它,这里不会有任何您想要使用的歧义。
答案 2 :(得分:0)
C ++不允许您自动从枚举转换为int
,导致operator int
不需要(例如,它会使用E
转换,然后转换为{{ 1}})?我知道你说你不想删除它,但你确实确认它破坏了API兼容性吗?
如果这不是一个选项,最好的办法是添加int
和as_int
方法,以便在所需转化类型不明确的情境中使用。
答案 3 :(得分:0)
如果你专门解决编译器错误,只需使用条件编译来创建一个变通方法,并尽可能保持自包含。
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) <= 40300
typedef int E; // workaround
# define ENUM_TYPE // do not define an enum type as it's not fully supported
#else
# define ENUM_TYPE E // newer GCC supports enum better
#endif
enum ENUM_TYPE { consta, constb };
#undef ENUM_TYPE
...在此之后,您可以忘记解决方法,只需要一个操作员......
operator E() const { return e;}
答案 4 :(得分:0)
规范说明条件(转换值):
条件应为整数类型,枚举类型或类型,其中存在单个转换函数为积分或枚举类型。
您的类类型有3个转换函数到积分或枚举类型,因此它很容易失败。如果删除operator int
重载,它甚至不起作用,因为那时仍然有2个转换函数。没有重载解决方案。如果它不写任何东西
operator E
重载
明确的演员阵容将是一个安全的赌注。同样奇怪的方法是使用op+
,但出于清晰原因我不会采取这种方式
switch (+x) { /* Don't do this in the wild */
case consta: // ..
case constb: // ..
}