正在替换 QVariant::Handler::canConvert

Replacing QVariant::Handler::canConvert

是否可以将我们自己的代码注入QVariant::canConvert?

我正在添加对我们自己的通用值容器和 Qt 版本 (QVariant) 之间转换的支持,主要基于此处的建议 How to support comparisons for QVariant objects containing a custom type?

我很确定这个问题的答案是 "it can't be done",浏览源代码显示 QVariant::canConvert 的实现没有调用处理程序,但我想我还是会问出来出于病态的好奇心。

https://github.com/qtproject/qt/blob/b05d05fd9ce2aeedfaf805a7ed9007a93c902bc9/src/corelib/kernel/qvariant.cpp#L2719

在 QVariant 实现中是否有任何随机位置,我们可以在其中获得对这种功能的某种挂钩(无需重新编译 Qt),如果没有,用于 anything/why 的 Handler 函数是否可以做到这一点存在?大多数情况下 - 有什么解决此问题的建议吗?

当然,您可以将 QVariant::canConvert() 与您的自定义数据类型一起使用。唯一需要注意的是,您必须向类型系统注册该类型。如果您不这样做,您将通过 static_assert

收到友好的提醒

error: static assertion failed: Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system

例如,这段代码工作得很好,

struct Foo {
    int a, b;
};

Q_DECLARE_METATYPE(Foo)


int main()
{
        Foo foo {1, 2};
        QVariant variant = QVariant::fromValue(foo);
        qDebug() << variant.canConvert<Foo>();
}

如果您想覆盖默认模板,您只需提供自己的专业化即可,

template<>
bool QVariant::canConvert<Foo>() const {
    qDebug() << "Hello from my specialization!";
    return userType() == qMetaTypeId<Foo>();
};

没有"handlers"因为这都是模板化的。请注意 - 虽然您可以专门化 QVariant::value() 之类的模板,但即使您专门化 int 案例,它也不会影响 QVariant::toInt() 和类似模板。例如,

template<>
int QVariant::value<int>() const
{
    if (userType() == qMetaTypeId<Foo>()) {
        return value<Foo>().a + value<Foo>().b;
    };

    return toInt();
}

....

qDebug() << variant.value<int>() << variant.toInt();

生产,

3 0