diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 023dafb223..255816d0ba 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -66,6 +66,14 @@ template struct QListSpecialMethods { }; template <> struct QListSpecialMethods; 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 class QList : public QListSpecialMethods { +public: + struct MemoryLayout + : QtPrivate::if_< + QTypeInfo::isStatic || QTypeInfo::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(); diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp index 95744051e4..1207986dde 100644 --- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -35,6 +35,17 @@ #include #include +template +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::MemoryLayout())) == sizeof(Yes) }; +}; + struct Movable { Movable(char input = 'j') : i(input) @@ -235,6 +246,27 @@ Q_STATIC_ASSERT(!QTypeInfo::isStatic); Q_STATIC_ASSERT(QTypeInfo::isComplex); Q_STATIC_ASSERT(QTypeInfo::isStatic); Q_STATIC_ASSERT(QTypeInfo::isComplex); +// iow: +Q_STATIC_ASSERT(( is_qlist_array_memory_layout ::value)); +Q_STATIC_ASSERT((!is_qlist_array_memory_layout ::value)); + +Q_STATIC_ASSERT((!is_qlist_array_memory_layout ::value)); +Q_STATIC_ASSERT((!is_qlist_array_memory_layout::value)); +Q_STATIC_ASSERT(( is_qlist_array_memory_layout ::value)); +Q_STATIC_ASSERT(( is_qlist_array_memory_layout ::value)); +Q_STATIC_ASSERT((!is_qlist_array_memory_layout ::value)); + +Q_STATIC_ASSERT(( is_qlist_array_memory_layout ::value)); +Q_STATIC_ASSERT(( is_qlist_array_memory_layout::value)); +Q_STATIC_ASSERT(( is_qlist_array_memory_layout ::value)); +Q_STATIC_ASSERT((!is_qlist_array_memory_layout ::value)); +Q_STATIC_ASSERT((!is_qlist_array_memory_layout ::value)); + +Q_STATIC_ASSERT((!is_qlist_array_memory_layout ::value)); +Q_STATIC_ASSERT(( is_qlist_array_memory_layout::value)); +Q_STATIC_ASSERT((!is_qlist_array_memory_layout ::value)); +Q_STATIC_ASSERT((!is_qlist_array_memory_layout ::value)); +Q_STATIC_ASSERT(( is_qlist_array_memory_layout ::value)); class tst_QList : public QObject {