根据QT文档, QVariant::operator== 如果该变体包含自定义类型,则无法正常工作:

bool qvariant ::操作员==(const Qvariant&v)const

将此QVariant与V进行比较,如果它们相等,则将其返回;否则返回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 找到与特定枚举值相对应的项目索引。

有帮助吗?

解决方案

明显的答案是将数据抛弃 var1.value<MyEnum>() == var2.value<MyEnum>() 比较它们,但这需要您在比较时知道类型。在您的情况下,这可能是可能的。

如果您只是使用枚举,也可以将其转换为QVariant中的int。

编辑:要澄清搜索 QComboBox, , 它 使用组合框的模型查找数据. 。具体来说,它使用了 match() 功能 QAbstractItemModel 检查平等。幸运的是,此功能是虚拟的,因此您可以在子类中覆盖它。

其他提示

尝试hack qvariant,通过原型定义功能

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

并将其设置为Qvariant处理程序;使用QVariant QT使用处理程序:

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

};

您必须创建功能并将其设置为处理程序。不要忘记打电话 HackVariant::hackIt() 在使用前的main.cpp中(var1 == var2)。

QT 5的解决方案

自第5.2版以来,QT可以开箱即用。看 qvariant ::操作员==qmetatype :: registerComparators.

QT 4的解决方案

如果您仍在使用QT 4,并且不能(或不希望)升级到QT 5,则可以使用 CustomVariantComparator 我为我的一个项目写的课。

您可以按以下方式使用它。假设我们有课 Foo 哪个实施 operator== 并应在 QVariant:

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

然后,只需 Q_DEFINE_COMPARATOR 宏观旁边的实现 Foo (即在 Foo.cpp 文件,但不在 Foo.h 文件):

Q_DEFINE_COMPARATOR(Foo)

下一个, 构建您的 QApplication (或者 QCoreApplication)实例,启用自定义变体比较器(只能完成一次):

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

现在,以下代码段将按预期工作(即调用 Foo::operator==).

QVariant::fromValue(Foo()) == QVariant::fromValue(Foo())
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top