错误:不明确的默认类型转换(c++)

error: ambiguous default type conversion (c++)

本文关键字:c++ 类型转换 默认 不明确 错误      更新时间:2023-10-16

我有一个类,它封装了一个枚举,以便于打印、序列化等。
我希望能够在switch语句中使用它作为传统枚举,因此在gcc-4.3之前我一直使用int((重载器。然而,我的代码现在中断了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"answers"Wrap::operator int((const">

这是库的一部分,我希望代码能在所有版本上运行,因此删除int重载器不是一个选项。

如果您专门处理编译器错误,只需使用条件编译来创建一个变通方法,并使其尽可能独立。

#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;}

将行更改为

switch ((E)x) {

枚举和int在编译器中非常相似(在内存中可能完全相同(,因此同时拥有这两种类型会让人感到困惑。如果你特别抛出它,这里不会有任何歧义,你想使用。

您可以通过static_cast:自己选择转换来解决歧义

switch(static_cast<E>(x))

另一种选择是使一个或多个转换运算符explicit——这将通过限制编译器的选项来解决歧义。

但是,explicit转换运算符仅适用于编译器不支持的C++0x。

C++是否允许您自动从枚举转换为int,从而使operator int不需要(例如,它将使用E转换,然后转换为int(?我知道你说过你不想删除它,但你真的确认它破坏了API兼容性吗?

如果这不是一个选项,那么最好的选择可能是添加as_intas_E方法,以便在所需转换类型不明确的上下文中使用。

规范说明了条件(切换值(:

条件应为积分类型、枚举类型或存在单个转换函数到积分或枚举类型的类类型。

您的类类型有3个到整型或枚举类型的转换函数,因此它很容易使该约束失效。如果去掉operator int重载,它甚至不会起作用,因为还有2个转换函数。没有过载解决方案。如果它无论如何都不写任何,那么也不需要非常量的operator E重载

明确的演员阵容是一个安全的选择。同样奇怪的方法是使用op+,但出于清晰的原因,我不会采用

switch (+x) { /* Don't do this in the wild */
  case consta: // ..
  case constb: // ..
}