运算符T()未在赋值中使用

时间:2015-09-18 12:23:21

标签: c++ qt implicit-conversion overload-resolution conversion-operator

我对此感到有点困惑。让我们假设我有一个帮助类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&#之一39; s operator=接受,但即使定义了这种转换,它仍然不起作用。

修改 问题似乎来自不同operator T()成员的多个定义。在这种情况下operator int()

1 个答案:

答案 0 :(得分:6)

我无法访问带有Qt库的在线编译器,但这是我从QStringQVariant的公共文档拼凑而成的内容:

#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

d("text")d2("text2")直接初始化,通过构造函数转换char const* -> QVariant

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

复制初始化 QString str = d忽略了对由

生成的临时QString对象的QString复制构造函数的调用
Data::operator QString() const

现在出现错误:str = d2赋值会尝试将各种赋值运算符QString::operator=重载到您的Data参数。一旦Data有多个转换运算符(例如QStringint),您将获得重载决策歧义,因为QString具有常规赋值operator=(QString)以及operator=(char)(可以int)。

TL; DR 只有一条施工路线:char const* -> QVariant -> Data。但是有两条路由Data -> QStringData -> int -> char导致赋值运算符的有效参数。

修复:在您自己的代码中使用explicit转化运算符(或删除其中一个或多个)。