Ambiguous string :: operator =调用类型,隐式转换为int和string

M2t*_*2tM 9 c++ string conversion-operator overload-resolution implicit-conversion

鉴于以下计划:

#include <iostream>
#include <string>
using namespace std;
struct GenericType{
   operator string(){
      return "Hello World";
   }
   operator int(){
      return 111;
   }
   operator double(){
      return 123.4;
   }
};
int main(){
   int i = GenericType();
   string s = GenericType();
   double d = GenericType();
   cout << i << s << d << endl;
   i = GenericType();
   s = GenericType(); //This is the troublesome line
   d = GenericType();
   cout << i << s << d << endl;
}
Run Code Online (Sandbox Code Playgroud)

它在Visual Studio 11上编译,但不是clang或gcc.这是有问题的,因为它要含蓄从转换GenericTypeint一个char,但它也可以返回string等有歧义(operator=(char)并且operator=(string)都匹配GenericType).

但是,复制构造函数很好.

我的问题是:如何在不修改main内容的情况下解决这种歧义?我需要做些什么才能修改GenericType以处理这种情况?

Jam*_*lis 10

我相信gcc和clang是正确的.

有两个operator=重载:

string& operator=(string const& str); // (1)
string& operator=(char ch);           // (2)
Run Code Online (Sandbox Code Playgroud)

这两个operator=重载都需要从您的类型参数进行用户定义的转换GenericType. (1)要求使用转换为string.(2)要求使用转换int,然后进行标准转换char.

重要的是两个重载都需要用户定义的转换.要确定其中一个转换是否比另一个更好,我们可以查看重载决策规则,特别是C++11§13.3.3.2/ 3中的以下规则(为清晰起见重新格式化):

用户定义的转换序列U1比另一个用户定义的转换序列的更好的转换序列U2,如果

  1. 它们包含相同的用户定义转换函数或构造函数或聚合初始化和

  2. 第二标准转换序列U1优于第二标准转换序列U2.

请注意,并且连接规则的两个部分,因此必须满足这两个部分.规则的第一部分不满足:两个用户定义的转换序列使用不同的用户定义转换函数.

因此,转换都不是更好,并且调用是模糊的.

[我没有很好的建议如何在不改变定义的情况下解决问题main().隐含的转换通常不是一个好主意; 它们有时非常有用,但更频繁地它们可能会导致过载模糊或其他奇怪的重载行为.

有一个gcc bug报告,其中描述了这个问题,并按设计解决: 编译器错误地诊断了ambigous operator overload.