コンテナに異なるオブジェクトを持たせたい理由は、おそらく設計上の欠陥です。ただし、異なるオブジェクト タイプの混合を含むことができるバッグ コレクションの概念を持つ Smalltalk など、一部の言語はこれをサポートします。Qt には何らかのバッグ コンテナー クラスが既にある可能性がありますが、その存在を知りません。
単一のコンテナー内に型が混在するというこの概念は、厳密に型指定された C++ の世界ではうまく機能しません。QVariant
バリアントオブジェクトは最も近いものであり、サブクラス化して構造体を処理するためにいくつかのビットを追加することで実行できる独自の「スーパーバリアント」クラスを作成しない限り、非整数型の場合でもそうではありません。
なぜこの機能が必要なのか、もう一度自問自答してください。他の場所で実装されたより単純なソリューションは、おそらくそのようなコンテナーの必要性を軽減します。
QMap<QString, QVariant>
編集:それが機能するかどうかを判断するのに役立つQuickieの例。
class SomeObject
{
public:
SomeObject() // default
: someInt(0), someDouble(0) {}
SomeObject(int i, double d) // explicit
: someInt(i), someDouble(d) {}
int GetSomeInt() const { return someInt; }
double GetSomeDouble() const { return someDouble; }
private:
int someInt;
double someDouble;
};
// must be outside of namespace
Q_DECLARE_METATYPE(SomeObject)
// then you can do stuff like this:
QMap<QString, QVariant> mapNameToValue;
// populate map
mapNameToValue["UserName"] = "User";
mapNameToValue["Port"] = 10101;
mapNameToValue["PI"] = 3.14159265;
mapNameToValue["DateTime"] = QDateTime::currentDateTime();
QVariant userValue;
userValue.setValue(SomeObject(5, 34.7));
mapNameToValue["SomeObject"] = userValue;
// read from map
QString userName = mapNameToValue["UserName"].toString();
unsigned int port = mapNameToValue["Port"].toUInt();
double PI = mapNameToValue["PI"].toDouble();
QDateTime date = mapNameToValue["DateTime"].toDateTime();
SomeObject myObj = mapNameToValue["SomeObject"].value<SomeObject>();
int someInt = myObj.GetSomeInt();
double someDouble = myObj.GetSomeDouble();
QVariant
多くの型を処理し、テンプレート メソッドsetValue
とvalue<>
ユーザー定義型も備えています。上記で簡単に示したように、Q_DECLARE_METATYPE
マクロを使用して登録し、変換が失敗QMetaType
した場合に備えてデフォルトのコンストラクターを提供する必要があります。value<>
特定の比較演算子をサポートしないので、独自のバージョンのQVariant
andを作成して、QMetaType
必要な追加の型をうまく操作して、より一貫性を感じられるようにします。