c++ - tag - meta verifizierungs snippet



Wie können Vergleiche für QVariant-Objekte unterstützt werden, die einen benutzerdefinierten Typ enthalten? (2)

Lösung für Qt 5

Qt unterstützt dies ab Version 5.2. Siehe QVariant::operator== und QMetaType::registerComparators .

Lösung für Qt 4

Wenn Sie Qt 4 noch verwenden und noch nicht auf Qt 5 aktualisieren können (oder nicht möchten), können Sie die CustomVariantComparator Klasse verwenden, die ich für eines meiner Projekte geschrieben habe.

Sie können es wie folgt verwenden. Nehmen wir an, wir haben eine Klasse Foo die operator== implementiert und in einem QVariant verwendet werden QVariant :

class Foo {
public:
    bool operator==(const Foo &other) { return ...; }
};
Q_DECLARE_METATYPE(Foo)

Q_DEFINE_COMPARATOR Makro Q_DEFINE_COMPARATOR einfach neben die Implementierung von Foo (dh in die Datei Foo.cpp , aber nicht in die Datei Foo.h ):

Q_DEFINE_COMPARATOR(Foo)

Als nächstes, nachdem Sie Ihre QApplication (oder QCoreApplication ) QCoreApplication , aktivieren Sie den benutzerdefinierten Variantenkomparator (dies muss nur einmal durchgeführt werden):

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    CustomVariantComparator::setEnabled(true);
    // more code...
}

Nun funktioniert das folgende Code-Snippet wie erwartet (dh Foo::operator== aufrufen).

QVariant::fromValue(Foo()) == QVariant::fromValue(Foo())

https://src-bin.com

Laut der Qt-Dokumentation QVariant::operator== nicht wie erwartet, wenn die Variante einen benutzerdefinierten Typ enthält:

bool QVariant :: operator == (const QVariant & v) const

Vergleicht diese QVariante mit v und gibt true zurück, wenn sie gleich sind. Andernfalls wird false zurückgegeben.

Bei benutzerdefinierten Typen werden ihre Gleichheitsoperatoren nicht aufgerufen. Stattdessen werden die Adressen der Werte verglichen.

Wie soll man das für Ihre benutzerdefinierten Typen sinnvoll machen? In meinem Fall speichere ich einen aufgezählten Wert in einem QVariant, z

In einer Kopfzeile:

enum MyEnum { Foo, Bar };

Q_DECLARE_METATYPE(MyEnum);

Irgendwo in einer Funktion:

QVariant var1 = QVariant::fromValue<MyEnum>(Foo);
QVariant var2 = QVariant::fromValue<MyEnum>(Foo);
assert(var1 == var2); // Fails!

Was muss ich anders machen, damit diese Behauptung wahr ist?

Ich verstehe, warum es nicht funktioniert - jede Variante speichert eine separate Kopie des aufgezählten Werts, so dass sie unterschiedliche Adressen haben. Ich möchte wissen, wie ich meinen Ansatz zum Speichern dieser Werte in Varianten ändern kann, so dass dies entweder kein Problem darstellt oder beide auf dieselbe zugrunde liegende Variable verweisen.

Ich glaube nicht, dass es für mich möglich ist, dass Gleichstellungsvergleiche funktionieren. Der Kontext ist, dass ich diese Enumeration als die UserData in Elementen in einer QComboBox und ich QComboBox::findData , um den QComboBox::findData zu finden, der einem bestimmten aufgezählten Wert entspricht.


Answer #1

Die offensichtliche Antwort besteht darin, die Daten mit var1.value<MyEnum>() == var2.value<MyEnum>() , um sie zu vergleichen, aber das erfordert, dass Sie den Typ beim Vergleich kennen. Es scheint, als wäre das in Ihrem Fall möglich.

Wenn Sie nur Enums verwenden, können Sie diese auch in QVariant in einen Int-Speicher konvertieren.

Bearbeiten: Zur Klärung der Suche nach einer QComboBox wird das Modell des Kombinationsfelds verwendet, um die Daten zu finden . Insbesondere verwendet es die Funktion match() von QAbstractItemModel , um auf Gleichheit zu prüfen. Glücklicherweise ist diese Funktion virtuell, sodass Sie sie in einer Unterklasse überschreiben können.





qvariant