Как QList решает, хранить ли указатели или сами элементы?

От документы:

Внутри QList представлен в виде массива указателей на элементы.
типа T. Если T сам является типом указателя или базовым типом, который не
больше, чем указатель, или если T является одним из общих классов Qt, то
QList хранит элементы непосредственно в массиве указателей.

Мне интересно знать, как QList «решить», хранить ли указатели или сами предметы в зависимости от типа?

Они делают это, используя некоторый эзотерический шаблонный синтаксис?

1

Решение

Давайте прочитаем источник (я использую Qt 4.8).

qlist.h:

struct Node {
void *v;
#if defined(Q_CC_BOR)
Q_INLINE_TEMPLATE T &t();
#else
Q_INLINE_TEMPLATE T &t()
{ return *reinterpret_cast<T*>(QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
? v : this); }
#endif
};

QList использования QTypeInfo определить свойства типа. QTypeInfo декларируется для различных типов отдельно. В qglobal.h:

Объявление по умолчанию для неизвестного типа:

template <typename T>
class QTypeInfo
{
public:
enum {
isPointer = false,
isComplex = true,
isStatic = true,
isLarge = (sizeof(T)>sizeof(void*)),
isDummy = false
};
};

Декларация для указателей:

template <typename T>
class QTypeInfo<T*>
{
public:
enum {
isPointer = true,
isComplex = false,
isStatic = false,
isLarge = false,
isDummy = false
};
};

Макросы для удобного объявления информации о типе:

#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \
class QTypeInfo<TYPE > \
{ \
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) \
}; \
static inline const char *name() { return #TYPE; } \
}

#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
template<> \
Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)

Декларация для примитивных типов:

Q_DECLARE_TYPEINFO(bool, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(char, Q_PRIMITIVE_TYPE); /* ... */

Также он определен для определенных типов Qt, например в qurl.h:

Q_DECLARE_TYPEINFO(QUrl, Q_MOVABLE_TYPE);

Или в qhash.h:

Q_DECLARE_TYPEINFO(QHashDummyValue, Q_MOVABLE_TYPE | Q_DUMMY_TYPE);

когда QList использования QTypeInfo<T>компилятор подберёт ближайший подарок QTypeInfo определения.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]