Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何支持包含自定义类型的QVariant对象的比较?_C++_Qt_Qvariant - Fatal编程技术网

C++ 如何支持包含自定义类型的QVariant对象的比较?

C++ 如何支持包含自定义类型的QVariant对象的比较?,c++,qt,qvariant,C++,Qt,Qvariant,根据Qt文档,QVariant::operator=如果变量包含自定义类型,则它的工作方式可能与预期不同: bool QVariant::operator==(const QVariant&v)const 将此QV变体与v和 如果它们相等,则返回true; 否则返回false 对于自定义类型,其 不调用相等运算符。 相反,值的地址是 相比之下 如何让它对您的自定义类型有意义?在我的例子中,我将枚举值存储在QVariant中,例如 在标题中: enum MyEnum { Foo, Bar };

根据Qt文档,
QVariant::operator=
如果变量包含自定义类型,则它的工作方式可能与预期不同:

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

将此QV变体与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!
QVariant var1=QVariant::fromValue(Foo);
QVariant var2=QVariant::fromValue(Foo);
断言(var1==var2);//失败!
我需要做什么不同的事情才能使这个断言成为真实的

我理解它为什么不起作用——每个变量都存储枚举值的一个单独副本,因此它们有不同的地址。我想知道如何改变将这些值存储在变量中的方法,以便这不是问题,或者它们都引用相同的基础变量


我认为我不可能在需要平等比较的情况下工作。上下文是,我使用此枚举作为
QComboBox
中项目的用户数据,并且我希望能够使用
QComboBox::findData
定位与特定枚举值对应的项目索引。

显而易见的答案是使用
var1.value()==var2.value()将数据从
进行比较,但这需要您在比较时知道类型。在你的情况下,这似乎是可能的

如果您只是使用枚举,还可以将其转换为int以存储在QVariant中


编辑:如需了解有关搜索的详细信息,请单击它。具体来说,它使用的函数检查相等性。幸运的是,这个函数是虚拟的,因此您可以在子类中重写它。

试试hack qvariant,通过原型定义函数

typedef bool (*f_compare)(const Private *, const Private *);
并将其设置为qvariant handler; 要使用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);
     }

};
class HackVariant:private QVariant
{
公众:
静态void hackIt(){
origh=处理程序;
Handler*h=新处理程序;
*h=*或高;
h->convert=转换;
h->debugStream=hackStreamDebug;
handler=h;
}
私人:
静态bool转换(const QVariant::Private*d,QVariant::Type t,void*result,bool*ok)
{
//qDebug()=QVariant::UserType)
{
QString&str=*((QString*)结果);
标识符*标识符=(标识符*)(常量数据(d));
str=ident->toString();
}
其他的
返回原点->转换(d、t、结果、ok);
返回true;
}
静态调试(QDebug dbg、const QVariant&v){
if(v.canConvert())
dbg调试流(dbg,v);
}
静态常量处理程序*origh;
静态常量void*constData(常量QVariant::Private*d)
{
返回d->is_shared?d->data.shared->ptr:reinterpret_cast(&d->data.ptr);
}
};
您必须创建函数并将其设置为handler。使用前不要忘记在main.cpp中调用
HackVariant::hackIt()
(var1==var2)。

Qt 5的解决方案 Qt从5.2版开始就支持这种开箱即用的功能。见和

qt4的解决方案 如果您仍然在使用Qt4,并且还不能(或不想)升级到Qt5,那么您可以使用我为我的一个项目编写的

您可以按如下方式使用它。假设我们有一个类
Foo
,它实现了
操作符==
,应该在
QVariant
中使用:

class Foo {
public:
    bool operator==(const Foo &other) { return ...; }
};
Q_DECLARE_METATYPE(Foo)
然后,只需将
Q\u DEFINE\u COMPARATOR
宏放在
Foo
实现旁边(即在
Foo.cpp
文件中,但不在
Foo.h
文件中):

接下来,在构建
QApplication
(或
QCoreApplication
)实例后,启用自定义变量比较器(只需执行一次):

现在,下面的代码片段将按预期工作(即调用
Foo::operator==


显而易见的答案不起作用,因为我无法更改
QComboBox
在其
findData
方法中所做的事情。是的,我知道我可以将其存储为int,但这似乎不雅观。另外,当我现在使用枚举时,我可能希望以后以同样的方式使用类,因此我正在寻找一个通用的解决方案。然后您可以重写
match()
函数()在模型类中,并将其分配给
QComboBox
,因为这就是它对
findData
Edit进行比较的方式:请参见此处:这看起来非常有希望。我会回来接受这个答案,如果它有效的话,一旦我有机会尝试它。非常有效!我将
QStandardItemModel
子类化为
T
类型上模板化的类,并重新实现
match
,这样,如果正在搜索精确的匹配,并且要查找的变量可转换为
T
,则
match
方法将比较
值()
,而不是变体本身。谢谢很高兴它有帮助,不久前我意识到QComboBox可以引用QabstracteModel,它使许多接口变得更容易!其他答复:
Q_DEFINE_COMPARATOR(Foo)
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    CustomVariantComparator::setEnabled(true);
    // more code...
}
QVariant::fromValue(Foo()) == QVariant::fromValue(Foo())