为什么此赋值操作会导致不明确的函数调用

Why does this assignment operation results in ambiguous function call?

本文关键字:不明确 函数调用 赋值 操作 为什么      更新时间:2023-10-16

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

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

但是如果我像下面这样稍微更改main()函数的代码:

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

编译器给出以下错误消息(在此处查看现场演示(

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

为什么这个电话是模棱两可的?这背后的原因是什么?看起来有很多超载operator=,比如一个用于char,一个用于char*,一个用于const char*等。这就是上面的程序使编译器变得模棱两可。

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

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

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

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

你调用operator =,但如果它是一个常规函数,那就是一样的了:

void f(int x);
void f(const string &y);
int main() {
    BB b;
    f(b);
    return 0;
}

由于BB可以用intstring转换,编译器不知道该调用哪个f函数。

您的第一个示例工作的唯一原因是因为在那里调用了复制构造函数,并且它只将const string&作为参数,因此没有多个选择。