22

Qt のドキュメントによるとQVariant::operator==、バリアントにカスタム タイプが含まれていると、期待どおりに動作しません。

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

この QVariant を v と比較し、等しい場合は true を返します。それ以外の場合は false を返します。

カスタム型の場合、等値演算子は呼び出されません。代わりに、値のアドレスが比較されます。

カスタムタイプに対してこれを有意義に動作させるにはどうすればよいですか? 私の場合、列挙値を QVariant に格納しています。

ヘッダーで:

enum MyEnum { Foo, Bar };

Q_DECLARE_METATYPE(MyEnum);

関数のどこかで:

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

この主張が真実であるためには、どうすればよいでしょうか?

機能しない理由を理解しています。各バリアントは列挙値の個別のコピーを保存しているため、異なるアドレスを持っています。これらの値をバリアントに格納するアプローチを変更して、これが問題にならないようにするか、両方が同じ基になる変数を参照するようにする方法を知りたいです。

同等の比較が機能する必要があることを回避することは不可能だと思います。コンテキストは、この列挙を の項目の UserData として使用しており、特定の列挙値に対応する項目インデックスを見つけるためQComboBoxに使用できるようにしたいということです。QComboBox::findData

4

3 に答える 3

15

明白な答えは、データをwithからキャストしvar1.value<MyEnum>() == var2.value<MyEnum>()て比較することですが、比較するときはタイプを知っている必要があります。あなたの場合、これは可能かもしれないようです。

列挙型を使用しているだけの場合は、QVariantに格納するためにそれをintに変換することもできます。

編集:検索について明確QComboBoxするために、コンボボックスのモデルを使用してデータを検索します。具体的には、のmatch()関数を使用QAbstractItemModelして同等性をチェックします。幸い、この関数は仮想であるため、サブクラスでオーバーライドできます。

于 2010-05-19T20:05:29.577 に答える
4

qvariant をハックしてみて、プロトタイプで関数を定義する

typedef bool (*f_compare)(const Private *, const Private *);

qvariant ハンドラーに設定します。qvariant qt を使用するには、Handler を使用します。

struct Handler {
    f_construct construct;
    f_clear clear;
    f_null isNull;
  #ifndef QT_NO_DATASTREAM
    f_load load;
    f_save save;
 #endif
    f_compare compare;
    f_convert convert;
    f_canConvert canConvert;
    f_debugStream debugStream;
};

この例は、qvariant デバッグ出力をハックして文字列に変換する方法を示しています。これは非常に単純な例であり、問​​題に合わせて拡張する必要があります。「識別子」は私のカスタムタイプです。

class HackVariant : private QVariant
{
public:
     static void hackIt() {
         origh = handler;
         Handler* h = new Handler;
         *h = *origh;
         h->convert = convert;
         h->debugStream = hackStreamDebug;
         handler = h;
     }

private:
     static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, bool *ok)
     {
         //qDebug() << Q_FUNC_INFO << "type:" << d->type;
         if (d->type >= QVariant::UserType)
         {
             QString& str = *((QString*)result);
             Identifier* ident = (Identifier*)(constData(d));
             str = ident->toString();
         }
         else
             return origh->convert(d, t, result, ok);
         return true;
     }

     static void hackStreamDebug(QDebug dbg, const QVariant &v) {
         if (v.canConvert<Identifier>())
             dbg << v.value<Identifier>();
         else
             origh->debugStream(dbg, v);
     }

     static const Handler* origh;

     static const void *constData(const QVariant::Private *d)
     {
         return d->is_shared ? d->data.shared->ptr : reinterpret_cast<const void *>(&d->data.ptr);
     }

};

関数を作成してハンドラに設定する必要があります。使用前に main.cpp での呼び出しを忘れないでくださいHackVariant::hackIt()(var1 == var2)。

于 2012-08-15T16:59:27.220 に答える