The T () operator is not used in assignment

I am a little confused by this. Suppose I have a helper class Data

 class Data { public: Data(const QVariant &value) : m_Variant(value) { } operator QString() const { return m_Variant.toString(); } private: QVariant m_Variant; }; 

then when i do this:

 Data d("text"); QString str = d; //str becomes "text" 

it works, but when I keep doing:

 Data d2("text2"); str = d2; //does not compile 

he fails:

 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); 

But even giving

 operator const char*() const; 

Does not help. The conversion message simply disappears and the error remains unchanged. Is there any way to solve this problem besides adding

 QString &operator=(const Data &data); 

before QString or explicitly call

 str = QString(d2); 

?

I got confused because the compiler made it clear that the left operand is a QString , and it seems to be trying to invoke a conversion from Data to accept one of QString operator= , but even if such a conversion is determined that it is still does not work.

EDIT: The problem seems to come from several definitions of the different members of operator T() . In this case, operator int() .

+5
source share
1 answer

I do not have access to the online compiler with Qt libraries, but here is what I collected from the public documentation of QString and 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; } 

Living example

direct initialization d("text") and d2("text2") , convert char const* -> QVariant via constructors

 QVariant::QVariant(const char*) Data::Data(const QVariant&) 

copy-initialization QString str = d returns a call to the QString copy constructor to the temporary QString created by

 Data::operator QString() const 

Now for the error: the assignment str = d2 trying to match the various assignment operators QString::operator= overloads with the Data argument. As soon as Data has several conversion operators (for example, QString and int ), you will get ambiguity overload resolution, since QString has both regular assignment operator=(QString) and operator=(char) (which can take int ).

TL DR there is only one route to build: char const* -> QVariant -> Data . But there are two routes Data -> QString and Data -> int -> char , which lead to a valid argument for the assignment operator.

Bugfix: use explicit conversion operators in your own code (or delete one or more of them).

+6
source

All Articles