Рассмотрим следующую программу, она компилируется и работает нормально:
#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;
}
Компилятор выдает следующее сообщение об ошибке (Смотрите демо здесь)
[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 cast\n";
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
может быть брошен в любом int
или же string
компилятор понятия не имеет, какой f
функция для вызова.
Единственная причина, по которой работает ваш первый пример, заключается в том, что там вызывается конструктор копирования, и он занимает только const string&
в качестве аргумента, так что нет множественного выбора.