2012-06-18 49 views
10
#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()は何も出力しませんが、2番目の出力は期待どおりに "asdf"を出力します。ネストされた変数マップの "bar"キーをどのように値に割り当てるのですか?入れ子になったQVariantMapに割り当てる

答えて

11

問題は、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(); 
} 

はおそらく、あなたがそれをoverwrittingのではなく、既存のマップを変更したいです。あなたが大量のデータを格納考えているなら

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

:あなたは(深いコピーになります)、新しいデータを追加し、その後に戻ってマップを書き、既存のマップをコピーすることによってこれを達成することができますQVariantの使用を再検討したいかもしれません。

+0

ここでは2016年に到着する読者の皆さんに:Qt 5.1+とC++ 11コンパイラを使用すると、このコードは[私の答えは以下のようになります](http://stackoverflow.com/質問/ 11090846/assigning-to-nested-qvariantmap/37119292#37119292)。 –

2

また、トロイアが好きではない方法で行うこともできます。

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

またはあなたはそれがすべて安全で素敵行うと直接QVariantMapの代わりにQExplicitlySharedDataPointerを使用することができます。このように:

#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(); 
} 
1

qvariant_castが実行されると、オブジェクトがコピーされます。オブジェクトのポインタを使うべきです。 qvariant_castコードの代わりに次のコードを試すことができます。

QVariantMap* m = (QVariantMap*)(map["foo"].data()); 
(*m)["bar"] = "a"; 
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"; 
1

Starting from Qt 5.1としてそれを使用すると、簡単に、ネストされたQMapQVariantMapを構築するためにC++11 uniform initialization syntaxを使用することができます。

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" 
+0

私はこのアプローチで明白な警告に注意する必要があります:マップが既知のキーのセットを持っている場合にのみ動作します。 –

関連する問題