QTypeInfo: use C++11 type traits to deduce if a type is static or complex
All types that can be trivially copied and destructed are by definition relocatable, and we should apply those semantics when moving them in memory. Types that are trivial, are by definition not complex and should be treated as such. [ChangeLog][QtCore] Qt Containers and meta type system now use C++11 type traits (std::is_trivial, std::is_trivially_copyable and std::is_trivially_destructible) to detect the class of a type not explicitly set by Q_DECLARE_TYPEINFO. (Q_DECLARE_TYPEINFO is still needed for QList.) Done-with: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com> Change-Id: Iebb87ece425ea919e86169d06cd509c54a074282 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
ba304af284
commit
fc85a6b6b9
|
|
@ -4103,6 +4103,13 @@ bool qunsetenv(const char *varName)
|
|||
Example of a movable type:
|
||||
|
||||
\snippet code/src_corelib_global_qglobal.cpp 39
|
||||
|
||||
Qt will try to detect the class of a type using std::is_trivial or
|
||||
std::is_trivially_copyable. Use this macro to tune the behavior.
|
||||
For instance many types would be candidates for Q_MOVABLE_TYPE despite
|
||||
not being trivially-copyable. For binary compatibility reasons, QList
|
||||
optimizations are only enabled if there is an explicit
|
||||
Q_DECLARE_TYPEINFO even for trivially-copyable types.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -49,6 +49,26 @@ QT_BEGIN_NAMESPACE
|
|||
QTypeInfo - type trait functionality
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool qIsRelocatable()
|
||||
{
|
||||
#if defined(Q_CC_CLANG) || !defined(Q_CC_GNU) || Q_CC_GNU >= 501
|
||||
return std::is_trivially_copyable<T>::value && std::is_trivially_destructible<T>::value;
|
||||
#else
|
||||
return std::is_enum<T>::value || std::is_integral<T>::value;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool qIsTrivial()
|
||||
{
|
||||
#if defined(Q_CC_CLANG) || !defined(Q_CC_GNU) || Q_CC_GNU >= 501
|
||||
return std::is_trivial<T>::value;
|
||||
#else
|
||||
return std::is_enum<T>::value || std::is_integral<T>::value;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
The catch-all template.
|
||||
*/
|
||||
|
|
@ -61,9 +81,9 @@ public:
|
|||
isSpecialized = std::is_enum<T>::value, // don't require every enum to be marked manually
|
||||
isPointer = false,
|
||||
isIntegral = std::is_integral<T>::value,
|
||||
isComplex = !isIntegral && !std::is_enum<T>::value,
|
||||
isComplex = !qIsTrivial<T>(),
|
||||
isStatic = true,
|
||||
isRelocatable = std::is_enum<T>::value,
|
||||
isRelocatable = qIsRelocatable<T>(),
|
||||
isLarge = (sizeof(T)>sizeof(void*)),
|
||||
isDummy = false, //### Qt6: remove
|
||||
sizeOf = sizeof(T)
|
||||
|
|
@ -248,9 +268,9 @@ class QTypeInfo<TYPE > \
|
|||
public: \
|
||||
enum { \
|
||||
isSpecialized = true, \
|
||||
isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0), \
|
||||
isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && !qIsTrivial<TYPE>(), \
|
||||
isStatic = (((FLAGS) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), \
|
||||
isRelocatable = !isStatic || ((FLAGS) & Q_RELOCATABLE_TYPE), \
|
||||
isRelocatable = !isStatic || ((FLAGS) & Q_RELOCATABLE_TYPE) || qIsRelocatable<TYPE>(), \
|
||||
isLarge = (sizeof(TYPE)>sizeof(void*)), \
|
||||
isPointer = false, \
|
||||
isIntegral = std::is_integral< TYPE >::value, \
|
||||
|
|
|
|||
|
|
@ -342,6 +342,7 @@ struct Bar
|
|||
++failureCount;
|
||||
}
|
||||
}
|
||||
~Bar() {}
|
||||
|
||||
public:
|
||||
static int failureCount;
|
||||
|
|
@ -458,7 +459,7 @@ void tst_QMetaType::threadSafety()
|
|||
|
||||
namespace TestSpace
|
||||
{
|
||||
struct Foo { double d; };
|
||||
struct Foo { double d; public: ~Foo() {} };
|
||||
struct QungTfu {};
|
||||
}
|
||||
Q_DECLARE_METATYPE(TestSpace::Foo)
|
||||
|
|
@ -515,11 +516,17 @@ void tst_QMetaType::properties()
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
struct Whity { T t; };
|
||||
struct Whity { T t; Whity() {} };
|
||||
|
||||
Q_DECLARE_METATYPE( Whity < int > )
|
||||
Q_DECLARE_METATYPE(Whity<double>)
|
||||
|
||||
#if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501
|
||||
QT_BEGIN_NAMESPACE
|
||||
Q_DECLARE_TYPEINFO(Whity<double>, Q_MOVABLE_TYPE);
|
||||
QT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
void tst_QMetaType::normalizedTypes()
|
||||
{
|
||||
int WhityIntId = ::qMetaTypeId<Whity<int> >();
|
||||
|
|
@ -818,10 +825,13 @@ void tst_QMetaType::sizeOfStaticLess()
|
|||
QCOMPARE(size_t(QMetaType(type).sizeOf()), size);
|
||||
}
|
||||
|
||||
struct CustomMovable {};
|
||||
struct CustomMovable { CustomMovable() {} };
|
||||
#if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501
|
||||
QT_BEGIN_NAMESPACE
|
||||
Q_DECLARE_TYPEINFO(CustomMovable, Q_MOVABLE_TYPE);
|
||||
QT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
Q_DECLARE_METATYPE(CustomMovable);
|
||||
|
||||
class CustomObject : public QObject
|
||||
|
|
@ -850,13 +860,15 @@ public:
|
|||
};
|
||||
Q_DECLARE_METATYPE(CustomMultiInheritanceObject*);
|
||||
|
||||
class C { char _[4]; };
|
||||
class M { char _[4]; };
|
||||
class C { char _[4]; public: C() = default; C(const C&) {} };
|
||||
class M { char _[4]; public: M() {} };
|
||||
class P { char _[4]; };
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
#if defined(Q_CC_GNU) && Q_CC_GNU < 501
|
||||
Q_DECLARE_TYPEINFO(M, Q_MOVABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(P, Q_PRIMITIVE_TYPE);
|
||||
#endif
|
||||
QT_END_NAMESPACE
|
||||
|
||||
// avoid the comma:
|
||||
|
|
@ -902,7 +914,7 @@ QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(ADD_METATYPE_TEST_ROW)
|
|||
QT_FOR_EACH_STATIC_CORE_POINTER(ADD_METATYPE_TEST_ROW)
|
||||
#undef ADD_METATYPE_TEST_ROW
|
||||
QTest::newRow("TestSpace::Foo") << ::qMetaTypeId<TestSpace::Foo>() << false << true << false << false;
|
||||
QTest::newRow("Whity<double>") << ::qMetaTypeId<Whity<double> >() << false << true << false << false;
|
||||
QTest::newRow("Whity<double>") << ::qMetaTypeId<Whity<double> >() << true << true << false << false;
|
||||
QTest::newRow("CustomMovable") << ::qMetaTypeId<CustomMovable>() << true << true << false << false;
|
||||
QTest::newRow("CustomObject*") << ::qMetaTypeId<CustomObject*>() << true << false << true << false;
|
||||
QTest::newRow("CustomMultiInheritanceObject*") << ::qMetaTypeId<CustomMultiInheritanceObject*>() << true << false << true << false;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ private Q_SLOTS:
|
|||
void taskQTBUG_48780_pairContainingCArray();
|
||||
};
|
||||
|
||||
class C { char _[4]; };
|
||||
class M { char _[4]; };
|
||||
class C { C() {} char _[4]; };
|
||||
class M { M() {} char _[4]; };
|
||||
class P { char _[4]; };
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
|
|||
Loading…
Reference in New Issue