operator T() not used in assignment

限于喜欢 提交于 2019-12-05 10:14:31

I haven't got access to an online compiler with the Qt libraries, but here's what I pieced together 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;
}

Live Example

The direct-initializations of d("text") and d2("text2"), convert char const* -> QVariant through the constructors

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

The copy-initialization QString str = d elides a call to the QString copy constructor on a temporary QString object produced by

Data::operator QString() const

Now for the bug: the assignment of str = d2 tries to match the various assignment operators QString::operator= overloads to your Data argument. Once Data has multiple conversion operators (to QString and to int e.g.), you will get an overload resolution ambiguity because QString has both the regular assignment operator=(QString) as well as the operator=(char) (which can take int).

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

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!