为什么这个赋值操作会导致函数调用不明确?
Why does this assignment operation results in ambiguous function 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*
等。这就是上面的程序使编译器产生歧义。
你调用了operator =
,但是如果它是一个普通的函数,结果是一样的:
void f(int x);
void f(const string &y);
int main() {
BB b;
f(b);
return 0;
}
由于 BB
可以转换为 int
或 string
,编译器不知道要调用哪个 f
函数。
您的第一个示例之所以有效的唯一原因是因为复制构造函数在那里被调用,并且它只需要 const string&
作为参数,所以没有多个选择。
你的问题是你的模板转换运算符。
template<typename T>
operator T() const
{
std::cout << "Generic cast\n";
return 0;
}
允许 BB
转换为任何内容。因此,可以考虑采用不同类型的 std::string::operator=
的所有重载。因为它们都是有效的,所以没有办法解决歧义,你会得到错误。
如果您删除了模板转换,那么它将编译。模板转换也可以标记为 explicit
然后你可以使用 static_cast
到你想要的类型。
考虑以下它编译并运行良好的程序:
#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*
等。这就是上面的程序使编译器产生歧义。
你调用了operator =
,但是如果它是一个普通的函数,结果是一样的:
void f(int x);
void f(const string &y);
int main() {
BB b;
f(b);
return 0;
}
由于 BB
可以转换为 int
或 string
,编译器不知道要调用哪个 f
函数。
您的第一个示例之所以有效的唯一原因是因为复制构造函数在那里被调用,并且它只需要 const string&
作为参数,所以没有多个选择。
你的问题是你的模板转换运算符。
template<typename T>
operator T() const
{
std::cout << "Generic cast\n";
return 0;
}
允许 BB
转换为任何内容。因此,可以考虑采用不同类型的 std::string::operator=
的所有重载。因为它们都是有效的,所以没有办法解决歧义,你会得到错误。
如果您删除了模板转换,那么它将编译。模板转换也可以标记为 explicit
然后你可以使用 static_cast
到你想要的类型。