Почему эта операция присваивания приводит к неоднозначному вызову функции?

Рассмотрим следующую программу, она компилируется и работает нормально:

#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* и т.д. Это вышеупомянутая программа ставит компилятор в неоднозначность.

1

Решение

Ваша проблема — ваш оператор преобразования шаблонов.

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

Позволяет BB быть преобразованным во что угодно. Из-за этого все перегрузки std::string::operator= что взять другой тип может быть рассмотрено. Поскольку все они действительны, нет возможности устранить неоднозначность, и вы получите ошибку.

Если вы удалили преобразование шаблона, оно будет скомпилировано. Преобразование шаблона также может быть помечено как explicit и тогда вы можете использовать static_cast к типу, который вы хотите.

5

Другие решения

Ты звонишь operator =, но это было бы то же самое, если бы это была обычная функция:

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

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

поскольку BB может быть брошен в любом int или же stringкомпилятор понятия не имеет, какой f функция для вызова.

Единственная причина, по которой работает ваш первый пример, заключается в том, что там вызывается конструктор копирования, и он занимает только const string& в качестве аргумента, так что нет множественного выбора.

2