11
#include <QtCore/QCoreApplication>
#include <QVariant>
#include <QtDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QVariantMap map;
    map["foo"] = QVariant(QVariantMap());
    map["baz"] = "asdf";
    qvariant_cast<QVariantMap>(map["foo"])["bar"] = "a";

    qDebug() << qvariant_cast<QVariantMap>(map["foo"])["bar"].toString();
    qDebug() << map["baz"].toString();

    return a.exec();
}

我正在尝试分配给嵌套 QVariantMap 中的 QVariant。第一个 qDebug() 不输出任何内容,但第二个按预期输出“asdf”。如何将嵌套变量映射中的“bar”键分配给一个值?

4

5 回答 5

12

问题是 qvariant_cast 没有返回对其正在运行的 QVariant 内部的引用;它返回一个副本。因此,如果您用新的子地图覆盖顶级地图中的“foo”元素,代码将正常工作:

#include <QtCore/QCoreApplication>
#include <QVariant>
#include <QtDebug>

int main(int argc, char** argv)
{
    QCoreApplication a(argc, argv);
    QVariantMap map;
    map["foo"] = QVariant(QVariantMap());
    map["baz"] = "asdf";

    QVariantMap newMap;
    newMap["bar"] = "a";
    map["foo"] = QVariant(newMap);

    qDebug() << qvariant_cast<QVariantMap>(map["foo"])["bar"].toString();
    qDebug() << map["baz"].toString();

    return a.exec();
}

大概,您想修改现有地图而不是覆盖它。您可以通过复制现有地图、添加新数据(这将导致深层复制)然后将地图写回中来完成此操作:

QVariantMap existingMap = qvariant_cast<QVariantMap>(map["foo"]);
existingMap["bar"] = "a";
map["foo"] = QVariant(existingMap);

如果您正在考虑存储大量数据,您可能希望重新考虑使用 QVariant。

于 2012-06-18T21:34:54.123 回答
3

或者你可以按照手推车不喜欢的方式来做。

#include <QtCore/QCoreApplication>
#include <QVariant>
#include <QtDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QVariantMap map;
    map["foo"] = QVariant(QVariantMap());
    map["baz"] = "asdf";
    static_cast<QVariantMap>(map["foo"].data_ptr())["bar"] = "a";

    qDebug() << qvariant_cast<QVariantMap>(map["foo"])["bar"].toString();
    qDebug() << map["baz"].toString();

    return a.exec();
}

或者,您可以安全且美观地完成这一切,并使用 QExplicitlySharedDataPointer 而不是直接使用 QVariantMap。像这样:

#include <QtCore>
#include <QtDebug>
class VarMap : public QVariantMap, public QSharedData {};
typedef QExplicitlySharedDataPointer<VarMap> SharedVarMap;
Q_DECLARE_METATYPE(SharedVarMap)
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QVariantMap map;
    map["foo"] = SharedVarMap(new VarMap());
    map["baz"] = "asdf";
    map["foo"].value<SharedVarMap>()->["bar"] = "a";

    qDebug() << map["foo"].value<SharedVarMap>()->["bar"].toString();
    qDebug() << map["baz"].toString();

    return a.exec();
}
于 2012-08-28T12:49:21.963 回答
2

当 qvariant_cast 被执行时,对象被复制。你应该使用对象的指针。您可以尝试以下代码而不是 qvariant_cast 代码。

QVariantMap* m = (QVariantMap*)(map["foo"].data());
(*m)["bar"] = "a";
于 2015-01-27T03:15:34.090 回答
2
template <typename T>
inline T& getStoredValueRef(QVariant &v)
{
    const auto type = qMetaTypeId<T>(static_cast<T*>(nullptr));
    auto& d = v.data_ptr();
    if (type == d.type)
    {
        auto data = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
        return *data;
    }
    throw std::runtime_error("Bad type");
}

用它作为

(getStoredValueRef<QVariantMap>(map["foo"]))["bar"] = "a";

而且更深

(getStoredValueRef<QVariantMap>(
    (getStoredValueRef<QVariantMap>(map["foo"]))["bar"]))["zoo"] = "a";
于 2015-03-18T12:32:25.793 回答
1

从 Qt 5.1 开始,您可以使用C++11 统一初始化语法来构建嵌套QMapQVariantMap轻松的:

QVariantMap fooMap{
    {"bar", "a"}
};

QVariantMap map{
    {"foo", fooMap},   // nested map
    {"baz", "asdf"}
};

qDebug() << qvariant_cast<QVariantMap>(map["foo"])["bar"].toString();  // outputs "a"
qDebug() << map["baz"].toString();    // outputs "asdf"
于 2016-05-09T15:10:59.427 回答