5

Je suis un peu confus par cela. Laisse supposer que j'ai une classe d'aide Dataopérateur T() non utilisé dans l'affectation

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

private: 
    QVariant m_Variant; 
}; 

quand je fais ceci:

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

cela fonctionne mais quand je continue à faire:

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

il ne parvient se plaindre:

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

Mais même en fournissant

operator const char*() const; 

ne aide pas. Le message sur la conversion disparaît et l'erreur reste la même. Y at-il un moyen de résoudre cette autre que d'ajouter

QString &operator=(const Data &data); 

à QString ou d'appeler explicitement

str = QString(d2); 

?

Je suis confus parce que le compilateur clairement déduit à juste titre que l'opérande gauche est un QString et il essaie d'appeler apparemment la conversion de Data à ce qui l'un des operator= s de » la QString accepter, mais même si une telle conversion est définie, il ne fonctionne toujours pas.

EDIT: Le problème semble provenir de plusieurs définitions des différents membres operator T(). Dans ce cas operator int().

+2

la première affectation "correcte", ne devrait-elle pas être "QString str = d;" au lieu de "QString str = Data;"? – Gombat

+0

Qu'est-ce que 'Data'? Pourriez-vous fournir un code minimal pour cette classe? – Gombat

+0

@Gombat Correction de la faute de frappe et du squelette de données fourni. Dans mon application, les données ne sont pas un QVariant mais en réalité une valeur de rapidjson mais pour des raisons de simplicité j'ai utilisé QVariant dans l'exemple. – Resurrection

Répondre

6

Je n'ai pas accès à un compilateur en ligne avec les bibliothèques Qt, mais voici ce que je Rassemblé de la documentation publique de QString et 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

Le Direct-initialisations de d("text") et d2("text2"), convertir char const* -> QVariant à travers les constructeurs

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

La copie initialisationQString str = d Elide un appel au constructeur de copie QString sur un objet QString temporaire produit par

Data::operator QString() const 

Maintenant pour le bug: l'affectation de str = d2 tente de faire correspondre les différents opérateurs d'affectation QString::operator= surcharge votre argument Data. Une fois que Data a plusieurs opérateurs de conversion (à QString et à int par ex.), vous obtiendrez une ambiguïté de résolution de surcharge car QString a à la fois l'affectation normale operator=(QString) ainsi que la operator=(char) (qui peut prendre int).

TL; DR Il n'existe qu'une seule voie de construction: char const* -> QVariant -> Data. Mais il existe deux routes Data -> QString et Data -> int -> char qui conduisent à un argument valide pour l'opérateur d'affectation.

Correction: utilisez les opérateurs de conversion explicit dans votre propre code (ou supprimez-en un ou plusieurs).

+0

Explication complète de ce qui est le problème ici. J'ajouterai que pour les solutions voir le dernier commentaire par @dyp à l'OP. – Resurrection

+0

@Resurrection merci, mis à jour! – TemplateRex