Since this list has quietened down a bit over the past few days, I thought it 
would be a good time to throw this one into the mix for Qt5 discussion. The 
motivation for attaching the following to the Qt5 discussion is because it 
relates to specifics of binary compatibility and there is potential for changes 
made for Qt5 to impact the viability of the techniques discussed. For 
reference, full details for the following cat be found in issue QTBUG-15313.

The QMetaType documentation contains the following statement when talking about 
what types can be registered with QMetaType:

"Any class or struct that has a public default constructor, a public copy 
constructor, and a public destructor can be registered."

Looking more closely through the code for QMetaType and QVariant reveals why 
these restrictions exist, but it also reveals that the restrictions are 
unnecessary! There are some helper templates defined in the qmetatype.h header 
(specifically qMetaTypeConstructHelper() and qMetaTypeDeleteHelper()) which 
rely on these assumptions, but since they are templates, there's no reason why 
explicit specializations could not be provided to give alternative 
implementations that did not require the above-mentioned constraints. If I 
wanted to register a type that had a clonable interface but no copy 
constructor, I could provide an explicit specialization of 
qMetaTypeConstructHelper() which used the cloning mechanism instead of a copy 
constructor. Similarly, if my type had some kind of destroy() function instead 
of a public destructor, I could do a similar thing with qMetaTypeDeleteHelper().

The other place where this restriction comes up is in QVariant::value<T>(), 
which returns by value, not by reference. This is because it may need to 
convert from the underlying type to the requested type. (The implementation of 
this function calls qVariantValue() and qvariant_cast() which are both template 
functions that also return by value). If, however, the underlying type and the 
requested type are the same, this involves copies that could be avoided. In 
this situation, QVariant::constData() (or potentially QVariant::data()) could 
be used to access the underlying data without having to copy it. Currently, 
QVariant::constData() is not documented as being part of the public API, but it 
effectively *is* part of the public API because inlined templates in the 
qvariant.h header call it and hence it has to be available to preserve binary 
compatibility.

What all this means is that if a developer wants to register a type that does 
not satisfy the constructor and destructor requirements, they can supply their 
own qMetaTypeConstructHelper() and/or qMetaTypeDeleteHelper() template 
specializations. They could then also choose to either have their type not 
support QVariant::value() (which would be a compile-time error) or they could 
also provide a specialization for QVariant::value() as well. And there is one 
important aspect to all this:

NO CHANGE WOULD BE REQUIRED TO ANY QT CODE AND THIS WORKS BACK AT LEAST AS FAR 
AS QT 4.5. ALL THAT WOULD NEED ALTERING IS THE QT DOCUMENTATION!!!

My main reason for bringing this up here on this list is that I'd like to see 
the above continue to be possible in Qt5. We do exactly what is discussed above 
in our own code, and we know it has to be safe for as long as Qt preserves 
binary compatibility. It is a very useful technique, particularly where your 
code wants to make use of QtScript (QVariants become quite useful in that 
context when passing data to/from C++). This idea didn't get much love in the 
bug report, but I'd like to see it at least considered in the Qt5 context. 
After all, it really only requires documenting things that are required for 
preserving binary compatibility anyway!

--
Dr Craig Scott
Computational Software Engineering Team Leader, CSIRO (CMIS)
Melbourne, Australia



_______________________________________________
Qt5-feedback mailing list
[email protected]
http://lists.qt.nokia.com/mailman/listinfo/qt5-feedback

Reply via email to