删除转换会导致模棱两可的过载?

时间:2018-07-13 00:20:55

标签: c++ visual-c++

我们的代码是多平台的。我使用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以外,还有什么方法可以达到预期的效果?

1 个答案:

答案 0 :(得分:1)

最简单的解决方案是将操作符bool声明为explicit。在ifwhilefor中用作条件时,显式运算符将被调用,但在函数调用中进行隐式转换时将被忽略。

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