运算符T()未在分配中使用 [英] operator T() not used in assignment

查看:151
本文介绍了运算符T()未在分配中使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对此我有点困惑.假设我有一个帮助器类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,而且显然正在尝试调用从DataQStringoperator=之一接受但不接受的转换即使定义了这种转换,它仍然不起作用.

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

解决方案

我无法使用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;
}

在线示例

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

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

复制初始化 QString str = d取消了对由

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

生成的临时QString对象的QString复制构造函数的调用

Data::operator QString() const

现在是该错误的地方:str = d2 assignment 试图匹配各种赋值运算符QString::operator=重载到您的Data参数.一旦Data具有多个转换运算符(例如,转换为QStringint),您将得到重载分辨率的歧义,因为QString同时具有常规赋值operator=(QString)operator=(char)(可以取int).

TL; DR ,只有一种构建路径:char const* -> QVariant -> Data.但是有两条路径Data -> QStringData -> int -> char导致赋值运算符的有效参数.

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

I am a bit confused by this. Lets assume 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 continue to do:

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

it fails complaining:

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 providing

operator const char*() const;

does not help. The message about conversion just disappears and the error remains the same. Is there a way to solve this other than adding

QString &operator=(const Data &data);

to QString or calling explicitly

str = QString(d2);

?

I am confused because the compiler clearly deduced correctly that the left operand is a QString and it is apparently trying to call conversion from Data to what would one of the QString's operator=s accept but even if such conversion is defined it still does not work.

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

解决方案

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

这篇关于运算符T()未在分配中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆