考虑以下程序编译并运行良好:
#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*
等。上面的程序将编译器放入歧义。
答案 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
可以在int
或string
中强制转换,因此编译器不知道要调用哪个f
函数。
你的第一个例子工作的唯一原因是因为复制构造函数在那里被调用,它只需要const string&
作为参数,所以没有多个选择。