Qt/C++ 将通用对象序列化为 QSettings

Posted

技术标签:

【中文标题】Qt/C++ 将通用对象序列化为 QSettings【英文标题】:Qt/C++ Serialize generic object into QSettings 【发布时间】:2020-03-23 15:06:20 【问题描述】:

我的应用程序中出现了几次我想将复合对象保存到 QSettings 中的情况:

template <typename T>
class AwsProperty

public:
    AwsProperty(T value, quint64 timestamp)
        m_data = value;
        m_timestamp = timestamp;
    
    AwsProperty()
    T value()return m_data;
    void update(T value,quint64 timestamp)m_data = value; m_timestamp = timestamp;
    quint64 timestamp()return m_timestamp;

    void toQDataStream(QDataStream &dstream)dstream << m_data << m_timestamp;
    void fromQDataStream(QDataStream &dstream)dstream >> m_data >> m_timestamp;
private:
    quint64 m_timestamp;
    T m_data;
;

typedef AwsProperty<qint32> AwsPropertyInt32;
Q_DECLARE_METATYPE(AwsPropertyInt32)
typedef AwsProperty<quint32> AwsPropertyUint32;
Q_DECLARE_METATYPE(AwsPropertyUint32)
typedef AwsProperty<bool> AwsPropertyBool;
Q_DECLARE_METATYPE(AwsPropertyBool)

cpp 看起来像这样:

template <typename T>
QDataStream& operator<<(QDataStream& out, const AwsProperty<T>& classObj)

    classObj.toQDataStream(out);
    return out;

template <typename T>
QDataStream& operator>>(QDataStream& in, const AwsProperty<T>& classObj)
    classObj.fromQDataStream(in);
    return in;

我在我的主目录中注册了它们:

  qRegisterMetaTypeStreamOperators<AwsPropertyInt32>("AwsPropertyInt32");
    qRegisterMetaTypeStreamOperators<AwsPropertyUint32>("AwsPropertyUint32");
    qRegisterMetaTypeStreamOperators<AwsPropertyBool>("AwsPropertyBool");

我得到的错误是:

/opt/XXXXXXXXXX/0.9.99/sysroots/cortexa9hf-neon-XXXXXX-linux-gnueabi/usr/include/QtCore/qmetatype.h:810: error: no match for ‘operator<<’ (operand types are ‘QDataStream’ and ‘const AwsProperty<int>’)
         stream << *static_cast<const T*>(t);
         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~

还有为什么没有为QDataStreamQString 定义流式操作符。

【问题讨论】:

【参考方案1】:

在实例化QSettings 之前,您必须使用qRegisterMetaTypeStreamOperators 将运算符注册到元类型系统。

此外,运算符的常量性以及 fromQDataStreamtoQDataStream 方法略有错误(有关所需的确切原型,请参阅链接)。

编辑:

这段代码对我有用:请注意,我更改了一些方法的常量并将运算符移到头文件中,因为它们是模板。

awsproperty.h

#include <QDataStream>

template <typename T>
class AwsProperty

public:
    AwsProperty(T value, quint64 timestamp)
        m_data = value;
        m_timestamp = timestamp;
    
    AwsProperty()
    T value()return m_data;
    void update(T value,quint64 timestamp)m_data = value; m_timestamp = timestamp;
    quint64 timestamp()return m_timestamp;

    void toQDataStream(QDataStream &dstream) const dstream << m_data << m_timestamp;
    void fromQDataStream(QDataStream &dstream)dstream >> m_data >> m_timestamp;
private:
    quint64 m_timestamp;
    T m_data;
;

template <typename T>
QDataStream& operator<<(QDataStream& out, const AwsProperty<T>& classObj) 
    classObj.toQDataStream(out);
    return out;


template <typename T>
QDataStream& operator>>(QDataStream& in, AwsProperty<T>& classObj) 
    classObj.fromQDataStream(in);
    return in;


typedef AwsProperty<qint32> AwsPropertyInt32;
Q_DECLARE_METATYPE(AwsPropertyInt32)
typedef AwsProperty<quint32> AwsPropertyUint32;
Q_DECLARE_METATYPE(AwsPropertyUint32)
typedef AwsProperty<bool> AwsPropertyBool;
Q_DECLARE_METATYPE(AwsPropertyBool)

ma​​in.cpp

#include "awsproperty.h"
#include <QSettings>
#include <QDebug>

int main(int argc, char *argv[])

    qRegisterMetaTypeStreamOperators<AwsPropertyInt32>("AwsPropertyInt32");
    qRegisterMetaTypeStreamOperators<AwsPropertyUint32>("AwsPropertyUint32");
    qRegisterMetaTypeStreamOperators<AwsPropertyBool>("AwsPropertyBool");
    QSettings set("/tmp/testsettings.conf");

    AwsPropertyInt32 a-2, 100;
    set.setValue("property", QVariant::fromValue(a));
    auto val = set.value("property").value<AwsPropertyInt32>();
    qDebug() << val.value() << " " << val.timestamp();

【讨论】:

我在我的问题中更正了它们,但错误仍然存​​在。 你的操作符是只在cpp文件中定义的吗?模板必须放在头文件中。

以上是关于Qt/C++ 将通用对象序列化为 QSettings的主要内容,如果未能解决你的问题,请参考以下文章

使用spring boot将JSON反序列化为带有通用对象列表的POJO

如何将属性序列化为 json 对象?

Newton JSON 如何将对象序列化为空括号?

如何将字符串反序列化为对象,然后在颤振中设置为泛型

如何使用mormot将通用TList序列化为JSON

如何使用 System.Text.Json API 将流反序列化为对象