PDA

View Full Version : Avoiding Q_DECLARE_METATYPE



moijhd
10th July 2013, 17:55
Hi,

I have a standard C++ object.



class A
{
// ...
};


I can't (and I don't want to) define it as a Qt type.

Though, I still like to put it in the model (QStandardItemModel for instance).

So far, I was able to but a raw pointer into the model with the very ugly following code :




// I have
const A &a = ; //...

// Writing
item->setData(
qVariantFromValue(
reinterpret_cast<void*>(
const_cast<A*>(
&a
)
)
),
Role
);

// Reading
const A &a = *reinterpret_cast<A*>(
const_cast<const void*>(
item->data(Role).value<void*>()
)
);



How bad is this ?

Anything better ?

Thanks !

PS0 : I read the method with Q_DECLARE_METATYPE.
PS1 : I could always create an intermediate Qt type which would embed my non Qt type...but that seems heavy too.

Santosh Reddy
10th July 2013, 18:21
Would this look simpler


...
QStandardItem item;
...
const A a0;
...
item.setData(reinterpret_cast<unsigned int>(&a), Role);
...
const A & a1 = *reinterpret_cast<const A*>(item.data(Role).toUInt());
//or
const A & a2 = *reinterpret_cast<const A*>(modelIndex.data(Role).toUInt());
...

moijhd
10th July 2013, 21:13
Okay for the casts factorisation, and the "toUInt()" simplification.

What the difference between the "void*" and the "unsigned int" casts ?

I suppose most machines will accept them indifferently. Though, I might have to mind about portability. So I guess the safest move id to go with "void*" ? But "unsigned int" simplifies a lot :D

ChrisW67
10th July 2013, 23:25
Why avoid the macro and invent work that can be hidden in the QVariant class for you?

moijhd
11th July 2013, 09:36
What if I have no control over the type ie the type is defined in a library ? I have to create a header include the library and including the Q_DECLARE_METATYPE and I will link that file when I need the meta type ? Fair enough.

By the way, can we guard Q_DECLARE_METATYPE through Qt ?

ChrisW67
11th July 2013, 10:19
What if I have no control over the type ie the type is defined in a library ?
If the type has a default constructor and can be copied then you can store it in a QVariant.
If the class does not meet the requirements then you can store a pointer (const or not) in a QVariant.
You need to arrange somewhere that Q_DECLARE_METATYPE() is invoked before you try to use the 3rd party type in a QVariant.



#include <QtCore>

// From some library header
class AClass {
public:
AClass() { }
~AClass() { }
AClass(const AClass &other) { }
};

class BClass {
public:
BClass() { }
~BClass() { }
private:
BClass(const BClass &other) { } // cannot be copied
};
// end of header

Q_DECLARE_METATYPE(AClass)
Q_DECLARE_METATYPE(const BClass*)

int main(int argc, char **argv) {
QCoreApplication app(argc, argv);

AClass aa;
QVariant av = QVariant::fromValue(aa);
// later
AClass ar = av.value<AClass>();

const BClass bb;
QVariant bv = QVariant::fromValue(&bb);
// later
const BClass *br = bv.value<const BClass*>();

return 0;
}



By the way, can we guard Q_DECLARE_METATYPE through Qt ?
I have no idea what this means.

moijhd
11th July 2013, 11:09
Ok thanks !

Guard for me :D



#ifndef Q_DECLARE_METATYPE_AClass
#define Q_DECLARE_METATYPE_AClass
Q_DECLARE_METATYPE(AClass)
#endif