Reputation: 1047
Is there a way to use Q_DECLARE_METATYPE() with enum class types? I know old enums work but what about these new, strongly typed, ones? Can't find anything regarding this problem elsewhere. I'm using the latest Qt version available.
Example:
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
Upvotes: 20
Views: 17568
Reputation: 48487
This is because when you use a plain old enum
:
enum Foo { A, B, C };
QVariant var = Foo::A;
the compiler in fact uses the following constructor to build up your var
instance:
QVariant(const QVariant& other);
And going further, the other
instance is created using the following non-explicit constructor:
QVariant(int val);
This is possible, because old enums
can be treated as integral values.
To sum up, this is what the compiler sees and does behind the scene:
int temp = Foo::A;
QVariant var = QVariant(temp);
As you know, enum class
es CAN NOT be treated as integral values without an explicit cast. Thus, the compiler cannot implicitly convert your type to int
, and invoke a matching constructor (to be precise: the best candidate from all available constructors). That is, there is a predefined set of constructors QVariant
offers. You cannot add a new one using Q_DECLARE_METATYPE
macro.
To use QVariant
with your own type, you should rather use QVariant::fromValue(const T& t)
function:
enum class Foo { A, B, C };
QVariant var = QVariant::fromValue(Foo::A);
or alternatively:
enum class Foo { A, B, C };
QVariant var;
var.setValue(Foo::A);
Upvotes: 26
Reputation: 324
Tried proposed solution using QVariant::fromValue
, but kept getting compiler errors of type:
Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system
My workround was to explicitly cast the enum values to int
when passing them onto a function requiring a QVariant
type, in my case when adding a QComboBox
item, and then casting it back to my enum class type at value retrieval.
In context of the original question, this would be something akin to:
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>()) };
Upvotes: 0