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

发布于 2024-10-31 01:19:34 字数 664 浏览 1 评论 0原文

我有一个类,它包装了一个枚举,以便于打印、序列化等。
我希望能够在 switch 语句中使用它作为传统的枚举,因此我一直使用 int() 重载器直到 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 重载器不是一个选项。

I have a class which wraps an enum for easy printing, serialization, etc.
I want to be able to use it in a switch statement as the traditional enum, hence I was using a int() overloader till gcc-4.3. However my code breaks now with 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;
} 

Compiler errors are:
error: ambiguous default type conversion from 'Wrap'
error: candidate conversions include 'Wrap::operator E() const' and 'Wrap::operator int() const'

This is part of a library and I want the code to work over all versions, hence removing the int overloader was not an option.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

戴着白色围巾的女孩 2024-11-07 01:19:34

如果您专门解决编译器错误,只需使用条件编译来创建解决方法并使其尽可能独立。

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

If you're specifically working around compiler bugs, just use conditional compilation to create a workaround and keep it as self-contained as possible.

#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

… after this point, you can forget about the workaround, and only one operator is necessary …

  operator E() const { return e;}
夏天碎花小短裙 2024-11-07 01:19:34

将行更改为

switch ((E)x) {

Enums 和 ints 在编译器中非常相似(并且在内存中可能相同),因此同时拥有这两者会让人感到困惑。如果你专门投射它,那么你想使用的地方就不会有任何歧义。

Change the line to

switch ((E)x) {

Enums and ints are very similar in the compiler (and probably identical in memory), so having both of those is confusing things. If you specifically cast it, here won't be any ambiguity in which you want to use.

抚笙 2024-11-07 01:19:34

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

switch(static_cast<E>(x))

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

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

You can resolve the ambiguity by selecting the conversion yourself with a static_cast:

switch(static_cast<E>(x))

Another option would be to make one or more of the conversion operators explicit -- that would resolve the ambiguity by limiting the compiler's options.

However, explicit conversion operators are available only for C++0x, which your compiler does not support.

那小子欠揍 2024-11-07 01:19:34

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

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

Doesn't C++ allow you to automatically convert from an enum to int, rendering the operator int unneeded (for example, it would use the E conversion and then convert to int)? I know you said you don't want to remove it but did you actually confirm it breaks API compatibility?

If that's not an option probably the best bet is to add as_int and as_E methods to use in contexts where the desired conversion type is ambiguous.

人事已非 2024-11-07 01:19:34

规格说明了条件(切换值):

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

您的类类型有 3 个到整型或枚举类型的转换函数,因此很容易违反此约束。如果删除 operator int 重载,它甚至无法工作,因为仍然有 2 个转换函数。不会发生过载解析。如果无论如何都不写入任何内容,则也不需要非常量operator E 重载

。显式强制转换将是一个安全的选择。同样相当奇怪的方法是使用 op+,但出于清晰的原因我不会采用它

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

The spec says for the condition (switched-over value):

The condition shall be of integral type, enumeration type, or of a class type for which a single conversion function to integral or enumeration type exists.

Your class type has 3 conversion functions to integral or enumeration types, so it easily fails this constraint. It won't even work if you remove the operator int overload, because then there are still 2 conversion functions. No overload resolution happens. There is also no need for a non-const operator E overload if it doesn't write anything anyway

An explicit cast will be a safe bet. Same rather weird way is to use op+, but which I wouldn't take for clarity reasons

switch (+x) { /* Don't do this in the wild */
  case consta: // ..
  case constb: // ..
}   
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文