【问题标题】:Why does this assignment operation results in ambiguous function call?为什么这个赋值操作会导致函数调用不明确?
【发布时间】:2015-10-29 23:03:51
【问题描述】:

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

#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*,等等。这就是上面的程序使编译器产生歧义。

【问题讨论】:

  • 在第一种情况下,这不是调用的赋值运算符,而是一个复制 ctor。但是我认为在第二种情况下,模板转换运算符和字符串转换之间存在歧义。
  • @MaMazav:是的,你是对的。但我的问题是关于 = 运算符出现的第二种情况。
  • 在 liveemo 页面上,错误消息还列出了编译器考虑在第二种情况下解决分配的所有候选者
  • @HellmarBecker,这个神奇的“livedemo”页面在哪里?
  • @Gread.And.Powerful.Oz:阅读问题以查看它。

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


【解决方案1】:

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

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

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

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

【讨论】:

  • 如果您进行模板化转换explicit,它也会编译。 explicit 的缺点是您需要一个 static_cast,但是对于转换运算符来说,明确可能是一个好主意。
  • @Niall 谢谢你。将其添加到答案中。
【解决方案2】:

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

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

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

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

您的第一个示例有效的唯一原因是复制构造函数在那里被调用,并且它只接受const string&amp; 作为参数,所以没有多项选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 2020-04-26
    • 1970-01-01
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多