Я немного смущен этим. Допустим, у меня есть вспомогательный класс Data
class Data
{
public:
Data(const QVariant &value) : m_Variant(value) { }
operator QString() const { return m_Variant.toString(); }
private:
QVariant m_Variant;
};
тогда, когда я делаю это:
Data d("text");
QString str = d; //str becomes "text"
это работает, но когда я продолжаю делать:
Data d2("text2");
str = d2; //does not compile
он не жалуется:
ambiguous overload for 'operator=' (operand types are 'QString' and 'Data')
candidates are:
...
QString &operator=(const QString &);
QString &operator=(QString &&);
QString &operator=(const char*); <near match>
no known conversion from Data to const char*
QString &operator=(char);
Но даже предоставляя
operator const char*() const;
не помогает. Сообщение о конвертации просто исчезает, а ошибка остается прежней. Есть ли способ решить эту проблему, кроме добавления
QString &operator=(const Data &data);
в QString
или явно
str = QString(d2);
?
Я в замешательстве, потому что компилятор четко сделал вывод, что левый операнд является QString
и, по-видимому, пытается вызвать преобразование из Data
на что бы один из QString
«s operator=
s принимают, но даже если такое преобразование определено, оно все равно не работает.
РЕДАКТИРОВАТЬ:
Проблема, кажется, исходит из нескольких определений разных operator T()
члены. В этом случае operator int()
,
У меня нет доступа к онлайн-компилятору с библиотеками Qt, но вот что я собрал из публичной документации QString
а также QVariant
:
#include <iostream>
struct QString
{
QString() = default;
QString(QString const&) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
QString &operator=(const QString &) { std::cout << __PRETTY_FUNCTION__ << '\n'; return *this; }
QString(char const*) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
QString &operator=(const char*) { std::cout << __PRETTY_FUNCTION__ << '\n'; return *this; }
QString(char) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
QString &operator=(char) { std::cout << __PRETTY_FUNCTION__ << '\n'; return *this; }
};
struct QVariant
{
QVariant(QString const&) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
QVariant(char const*) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
};
struct Data
{
Data(QVariant const&) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
operator QString() const { std::cout << __PRETTY_FUNCTION__ << '\n'; return QString(); }
operator int() const { std::cout << __PRETTY_FUNCTION__ << '\n'; return QString(); }
};
int main()
{
Data d("text");
QString str = d;
Data d2("text2");
str = d2;
}
Прямая-инициализация из d("text")
а также d2("text2")
, перерабатывать char const* -> QVariant
через конструкторы
QVariant::QVariant(const char*)
Data::Data(const QVariant&)
копия инициализация QString str = d
elides призыв к QString
скопировать конструктор на временный QString
объект производится
Data::operator QString() const
Теперь об ошибке: назначение из str = d2
пытается сопоставить различные операторы присваивания QString::operator=
перегрузки к вашему Data
аргумент. однажды Data
имеет несколько операторов преобразования (для QString
и к int
например, вы получите неоднозначность разрешения перегрузки, потому что QString
имеет как регулярное назначение operator=(QString)
так же хорошо как operator=(char)
(который может занять int
).
TL; DR есть только один маршрут для строительства: char const* -> QVariant -> Data
, Но есть два маршрута Data -> QString
а также Data -> int -> char
что приводит к действительному аргументу для оператора присваивания.
Исправить: использовать explicit
преобразование операторов в ваш собственный код (или удаление одного или нескольких из них).