QList: prepare for tag dispatching based on memory layout

Add one tag class for each of QList's three different memory layouts
to QListData, and inherit QList<T>::MemoryLayout from exactly one of
them.

To simplify overloading, added tag classes that express the negation
of the two extreme poles of memory layout (C-compatible and heap),
too. The "missing" one could be added when needed, too.

Change-Id: I45ea603731499fd3fdfb37d60a0a98fb22ac15ec
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2014-10-01 10:56:14 +02:00
parent 4c4940a744
commit 40d6e8adf5
2 changed files with 51 additions and 0 deletions

View File

@ -66,6 +66,14 @@ template <typename T> struct QListSpecialMethods { };
template <> struct QListSpecialMethods<QByteArray>;
struct Q_CORE_EXPORT QListData {
// tags for tag-dispatching of QList implementations,
// based on QList's three different memory layouts:
struct NotArrayCompatibleLayout {};
struct NotIndirectLayout {};
struct ArrayCompatibleLayout : NotIndirectLayout {}; // data laid out like a C array
struct InlineWithPaddingLayout : NotArrayCompatibleLayout, NotIndirectLayout {}; // data laid out like a C array with padding
struct IndirectLayout : NotArrayCompatibleLayout {}; // data allocated on the heap
struct Data {
QtPrivate::RefCount ref;
int alloc, begin, end;
@ -99,6 +107,17 @@ struct Q_CORE_EXPORT QListData {
template <typename T>
class QList : public QListSpecialMethods<T>
{
public:
struct MemoryLayout
: QtPrivate::if_<
QTypeInfo<T>::isStatic || QTypeInfo<T>::isLarge,
QListData::IndirectLayout,
typename QtPrivate::if_<
sizeof(T) == sizeof(void*),
QListData::ArrayCompatibleLayout,
QListData::InlineWithPaddingLayout
>::type>::type {};
private:
struct Node { void *v;
#if defined(Q_CC_BOR)
Q_INLINE_TEMPLATE T &t();

View File

@ -35,6 +35,17 @@
#include <QtTest/QtTest>
#include <QList>
template <typename T, class MemoryLayout>
class is_qlist_array_memory_layout {
struct No { char c; };
struct Yes { No n[2]; };
Q_STATIC_ASSERT(sizeof(No) != sizeof(Yes));
static No check(...);
static Yes check(MemoryLayout);
public:
enum { value = sizeof(check(typename QList<T>::MemoryLayout())) == sizeof(Yes) };
};
struct Movable {
Movable(char input = 'j')
: i(input)
@ -235,6 +246,27 @@ Q_STATIC_ASSERT(!QTypeInfo<Optimal>::isStatic);
Q_STATIC_ASSERT(QTypeInfo<Optimal>::isComplex);
Q_STATIC_ASSERT(QTypeInfo<Complex>::isStatic);
Q_STATIC_ASSERT(QTypeInfo<Complex>::isComplex);
// iow:
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<int, QListData::NotIndirectLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<int, QListData::IndirectLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Optimal, QListData::InlineWithPaddingLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Optimal, QListData::NotArrayCompatibleLayout>::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Optimal, QListData::NotIndirectLayout> ::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Optimal, QListData::ArrayCompatibleLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Optimal, QListData::IndirectLayout> ::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Movable, QListData::InlineWithPaddingLayout> ::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Movable, QListData::NotArrayCompatibleLayout>::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Movable, QListData::NotIndirectLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Movable, QListData::ArrayCompatibleLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Movable, QListData::IndirectLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Complex, QListData::InlineWithPaddingLayout> ::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Complex, QListData::NotArrayCompatibleLayout>::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Complex, QListData::NotIndirectLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Complex, QListData::ArrayCompatibleLayout> ::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Complex, QListData::IndirectLayout> ::value));
class tst_QList : public QObject
{