web-dev-qa-db-ja.com

Qt-列挙型クラスタイプのQ_DECLARE_METATYPE()

列挙型クラスタイプでQ_DECLARE_METATYPE()を使用する方法はありますか?古い列挙型が機能することは知っていますが、これらの新しい、強く型付けされた列挙型はどうですか?この問題に関するものは他に見つかりません。入手可能な最新のQtバージョンを使用しています。

例:

enum Foo
{
    A,
    B,
    C
};

Q_DECLARE_METATYPE(Foo)
QVariant var = Foo::A; // works fine

enum class Bar
{
    X,
    Y,
    Z
};

Q_DECLARE_METATYPE(Bar)
QVariant var = Bar::X; // doesn't compile
15
Venom

これは、単純な古いenumを使用する場合:

_enum Foo { A, B, C };
QVariant var = Foo::A;
_

実際、コンパイラは次のコンストラクタを使用してvarインスタンスを構築します。

_QVariant(const QVariant& other);
_

さらに、otherインスタンスは、次の非明示的なコンストラクターを使用して作成されます。

_QVariant(int val);
_

古いenumsを整数値として扱うことができるため、これは可能です。

要約すると、これはコンパイラが舞台裏で見て実行することです

_int temp = Foo::A;
QVariant var = QVariant(temp);
_

ご存知のように、_enum class_ esCAN NOTは、明示的なキャストなしで整数値として扱われます。したがって、コンパイラーは、型を暗黙的にintに変換し、一致するコンストラクターを呼び出すことはできません(正確には、使用可能なすべてのコンストラクターからの最良の候補)。つまり、QVariantが提供するコンストラクターの事前定義されたセットがあります。 _Q_DECLARE_METATYPE_マクロを使用して新しいマクロを追加することはできません。

独自のタイプでQVariantを使用するには、むしろ QVariant::fromValue(const T& t) 関数を使用する必要があります。

_enum class Foo { A, B, C };
QVariant var = QVariant::fromValue(Foo::A);
_

または代わりに:

_enum class Foo { A, B, C };
QVariant var;
var.setValue(Foo::A);
_
21
Piotr Skotnicki

Qt 5.5で追加された Q_ENUM を使用できます。

enum class Bar
{
    X,
    Y,
    Z
};
Q_ENUM(Bar)

QVariant var = QVariant::fromValue(Bar::X);
4
parsley72

QVariant::fromValueを使用して提案されたソリューションを試しましたが、次のタイプのコンパイラエラーが発生し続けました。

タイプが登録されていません。Q_DECLARE_METATYPEマクロを使用して、Qtのメタオブジェクトシステムに認識させてください。

私の回避策は、列挙型をint型を必要とする関数に渡すときに、列挙値を明示的にQVariantにキャストすることでした。私の場合、QComboBoxアイテムを追加して、それをキャストするときです。値の取得時に列挙型クラスタイプに戻ります。

元の質問のコンテキストでは、これは次のようなものになります。

enum class Foo { A, B, C };

// Elsewhere, adding item to QComboBox.
m_comboBox->addItem(tr("A"), static_cast<int>(Foo::A));

// Value retrieval from QComboBox item, somewhere else.
const auto foo { static_cast<Foo>(m_comboBox->currentData().value<int>()) };
0
tjansson