为什么这个赋值操作导致函数调用不明确?

时间:2015-10-29 14:35:36

标签: c++ assignment-operator function-call ambiguous-call

考虑以下程序编译并运行良好:

#include <iostream>
#include <string>
using std::string;
struct BB
{
 // generic cast
 template<typename T>
 operator T() const
 {   
   std::cout<<"Generic cast\n";
   return 0;
 }
 // string cast
 operator string() const
 { 
   std::cout<<"string cast\n";
   return string("hello");
 }
};
int main()
{
  BB b;
  string s = b; // copy constructor
}

但如果我稍微改变main()函数的代码如下:

int main()
{
  BB b;
  string s;
  s = b;
} 

编译器提供以下错误消息(See live demo here

[Error] ambiguous overload for 'operator=' (operand types are 'std::string {aka std::basic_string<char>}' and 'BB')

为什么这个电话不明确?这背后的原因是什么?看起来有很多重载的operator=char一样,一个用于char*,一个用于const char*等。上面的程序将编译器放入歧义。

2 个答案:

答案 0 :(得分:5)

您的问题是模板转换运算符。

template<typename T>
operator T() const
{
    std::cout << "Generic cast\n";
    return 0;
}

允许将BB转换为任何内容。因为可以考虑采用不同类型的std::string::operator=的所有重载。由于它们都是有效的,因此无法解决歧义并且您会收到错误。

如果您删除了模板转换,那么它将进行编译。模板转换也可以标记为explicit,然后您可以使用static_cast到您想要的类型。

答案 1 :(得分:2)

你打电话给operator =,但如果它是常规功能则会相同:

void f(int x);
void f(const string &y);

int main() {
    BB b;
    f(b);
    return 0;
}

由于BB可以在intstring中强制转换,因此编译器不知道要调用哪个f函数。

你的第一个例子工作的唯一原因是因为复制构造函数在那里被调用,它只需要const string&作为参数,所以没有多个选择。