首页 > 解决方案 > 删除导致模棱两可的过载的转换?

问题描述

我们的代码是多平台的。我使用 MSVC,我的同事使用 Clang 或 GCC。

我们的一个类有一个指针转换,它总是返回非nullptr. 由于在布尔表达式中意外使用它,我发现了一个问题,该表达式总是返回true. 所以,我删除了布尔转换运算符。

这对我来说非常有效(实际上在我们的程序中显示了我们正在执行此操作的其他十个地方),但是由于模棱两可的重载,我的同事无法再编译。

情况如下:

class Thingy
{
public:
  operator const double * () const
  {
    return xyz;
  }

  operator bool () const = delete;

private:
  double xyz[3];      
};

void func(const double *d)
{
}

void func(unsigned int i)
{
}

int main()
{
  Thingy a;
  func(a);
}

在 MSVC 上,func(const double *d)我会调用它。但是,在 GCC 上,它失败如下:

<source>: In function 'int main()':
<source>:27:9: error: call of overloaded 'func(Thingy&)' is ambiguous
   func(a);
         ^
<source>:16:6: note: candidate: 'void func(const double*)'
 void func(const double *d)
      ^~~~
<source>:20:6: note: candidate: 'void func(unsigned int)'
 void func(unsigned int i)
      ^~~~
Compiler returned: 1

如果您取出operator bool () const = delete;,它在 GCC 上可以正常工作,但是您没有以下保护:

Thingy b /* = callSomeFunction()*/;
if (!b)
{
  // whoops! never enters here! Would be nice for this to be a compiler error.
}
else
{
  // do something with the valid Thingy
}

我们认为,在 GCC/Clang 上,歧义在于func(const double*)使用转换为const double*调用和调用func(unsigned int)转换为之间bool,即使转换bool为显式无效。

为什么会这样?为什么 MSVC 允许它?除了可能之外,有什么方法可以达到预期的效果#ifdef _MSVC_VER吗?

标签: c++visual-c++

解决方案


最简单的解决方案是将运算符 bool 声明为explicit. 用作 a或中的条件if,将调用显式运算符,但对于函数调用的隐式转换将被忽略。whilefor

http://coliru.stacked-crooked.com/a/78dd309602295e79


推荐阅读