1+1=10

人生苦短,成长路上究竟在 扬长避短 还是 取长补短...

"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:

>   `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. 

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

We can find following code in qtypeinfo.h:

```cpp
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

  • http://doc.qt.digia.com/qq/qq19-containers.html
  • http://www.drdobbs.com/c-made-easier-plain-old-data/184401508

Comments