1+1=10

Debao's Blog...

"Qt Macro: Q_DECLARE_TYPEINFO"

Definition

Q_DECLARE_TYPEINFO is used to specialise a template class called QTypeInfo.

```cpp qtypeinfo.h

define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \

class QTypeInfo \ { \ public: \ enum { \ isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0), \ isStatic = (((FLAGS) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), \ isLarge = (sizeof(TYPE)>sizeof(void)), \ isPointer = false, \ isDummy = (((FLAGS) & Q_DUMMY_TYPE) != 0), \ sizeOf = sizeof(TYPE) \ }; \ static inline const char name() { return #TYPE; } \ }

define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \

template<> \ Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)

## Where Q_DECLARE_TYPEINFO is used?

The documention says that:

{% blockquote %}
   Q_DECLARE_TYPEINFO( Type, Flags)

   You can use this macro to specify information about a custom type Type. With accurate type information, Qt's generic containers can choose appropriate storage methods and algorithms.
{% endblockquote %}

Let's find where QTypeInfo is used in Qt's source code:

```cpp qlist.h
template <typename T>
class QList
{
    struct Node { void *v;
        Q_INLINE_TEMPLATE T &t()
        { return *reinterpret_cast<T*>(QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
                                       ? v : this); }
    };
//...

```cpp qvector.h template void QVector::reallocData(const int asize, const int aalloc, QArrayData::AllocationOptions options) { //... if (QTypeInfo::isStatic || (isShared && QTypeInfo::isComplex)) { // we can not move the data, we need to copy construct it while (srcBegin != srcEnd) { new (dst++) T(*srcBegin++); } } else { ::memcpy(static_cast(dst), static_cast(srcBegin), (srcEnd - srcBegin) * sizeof(T)); //...

## TYPEINFO flags

```cpp qtypeinfo.h
enum { /* TYPEINFO flags */
    Q_COMPLEX_TYPE = 0,
    Q_PRIMITIVE_TYPE = 0x1,
    Q_STATIC_TYPE = 0,
    Q_MOVABLE_TYPE = 0x2,
    Q_DUMMY_TYPE = 0x4
};
  • Q_PRIMITIVE_TYPE specifies that Type is a POD (plain old data) type with no constructor or destructor, or else a type where every bit pattern is a valid object and memcpy() creates a valid independent copy of the object.
  • Q_MOVABLE_TYPE specifies that Type has a constructor and/or a destructor but can be moved in memory using memcpy().
  • Q_COMPLEX_TYPE (the default) specifies that Type has constructors and/or a destructor and that it may not be moved in memory.

For QVector, When an insertion takes place, the elements that come after the point of insertion must be moved one position further. If T is a movable type, this is achieved using memmove(); otherwise, QVector needs to move the items one by one using operator=(). The same applies to removals in the middle.

{% img center /images/blog/2013/q_declare_typeinfo_qvector_insert.png %}

Reference

Comments