运算符T()未在分配中使用 [英] operator T() not used in assignment
问题描述
对此我有点困惑.假设我有一个帮助器类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
的operator=
之一接受但不接受的转换即使定义了这种转换,它仍然不起作用.
问题似乎来自于不同的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
取消了对由
Data d("text");
QString str = d; //str becomes "text"
生成的临时QString
对象的QString
复制构造函数的调用
Data::operator QString() const
现在是该错误的地方:str = d2
的 assignment 试图匹配各种赋值运算符QString::operator=
重载到您的Data
参数.一旦Data
具有多个转换运算符(例如,转换为QString
和int
),您将得到重载分辨率的歧义,因为QString
同时具有常规赋值operator=(QString)
和operator=(char)
(可以取int
).
TL; DR ,只有一种构建路径:char const* -> QVariant -> Data
.但是有两条路径Data -> QString
和Data -> 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;
}
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屋!