diff options
Diffstat (limited to 'src/corelib/global/qtypeinfo.h')
-rw-r--r-- | src/corelib/global/qtypeinfo.h | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 3d1bac8be9..255a2b33c6 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -2,14 +2,16 @@ // Copyright (C) 2016 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#include <QtCore/qglobal.h> +#ifndef QTYPEINFO_H +#define QTYPEINFO_H + +#include <QtCore/qcompilerdetection.h> #include <QtCore/qcontainerfwd.h> + #include <variant> #include <optional> #include <tuple> - -#ifndef QTYPEINFO_H -#define QTYPEINFO_H +#include <type_traits> QT_BEGIN_NAMESPACE @@ -19,6 +21,15 @@ class QDebug; QTypeInfo - type trait functionality */ +namespace QtPrivate { + +// A trivially copyable class must also have a trivial, non-deleted +// destructor [class.prop/1.3], CWG1734. Some implementations don't +// check for a trivial destructor, because of backwards compatibility +// with C++98's definition of trivial copyability. +// Since trivial copiability has implications for the ABI, implementations +// can't "just fix" their traits. So, although formally redundant, we +// explicitly check for trivial destruction here. template <typename T> inline constexpr bool qIsRelocatable = std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>; @@ -32,6 +43,8 @@ template <typename T> inline constexpr bool qIsValueInitializationBitwiseZero = std::is_scalar_v<T> && !std::is_member_object_pointer_v<T>; +} + /* The catch-all template. */ @@ -44,8 +57,8 @@ public: isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v<T>, isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral_v<T>, isComplex = !std::is_trivial_v<T>, - isRelocatable = qIsRelocatable<T>, - isValueInitializationBitwiseZero = qIsValueInitializationBitwiseZero<T>, + isRelocatable = QtPrivate::qIsRelocatable<T>, + isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<T>, }; }; @@ -92,6 +105,11 @@ public: [[deprecated("Use std::is_pointer instead")]] static constexpr bool isPointer = false; [[deprecated("Use std::is_integral instead")]] static constexpr bool isIntegral = false; static constexpr bool isValueInitializationBitwiseZero = false; + static_assert(!isRelocatable || + std::is_copy_constructible_v<T> || + std::is_move_constructible_v<T>, + "All Ts... are Q_RELOCATABLE_TYPE, but T is neither copy- nor move-constructible, " + "so cannot be Q_RELOCATABLE_TYPE. Please mark T as Q_COMPLEX_TYPE manually."); }; // QTypeInfo for std::pair: @@ -148,11 +166,15 @@ class QTypeInfo<TYPE > \ public: \ enum { \ isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && !std::is_trivial_v<TYPE>, \ - isRelocatable = !isComplex || ((FLAGS) & Q_RELOCATABLE_TYPE) || qIsRelocatable<TYPE>, \ + isRelocatable = !isComplex || ((FLAGS) & Q_RELOCATABLE_TYPE) || QtPrivate::qIsRelocatable<TYPE>, \ isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v< TYPE >, \ isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral< TYPE >::value, \ - isValueInitializationBitwiseZero = qIsValueInitializationBitwiseZero<TYPE>, \ + isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<TYPE>, \ }; \ + static_assert(!isRelocatable || \ + std::is_copy_constructible_v<TYPE > || \ + std::is_move_constructible_v<TYPE >, \ + #TYPE " is neither copy- nor move-constructible, so cannot be Q_RELOCATABLE_TYPE"); \ } #define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \ @@ -232,7 +254,7 @@ using expand_operator_equal_recursive = std::conjunction<expand_operator_equal<T template<typename T> struct expand_operator_equal_tuple : has_operator_equal<T> {}; template<typename T> -struct expand_operator_equal_tuple<std::optional<T>> : has_operator_equal<T> {}; +struct expand_operator_equal_tuple<std::optional<T>> : expand_operator_equal_recursive<T> {}; template<typename T1, typename T2> struct expand_operator_equal_tuple<std::pair<T1, T2>> : expand_operator_equal_recursive<T1, T2> {}; template<typename ...T> @@ -272,7 +294,7 @@ using expand_operator_less_than_recursive = std::conjunction<expand_operator_les template<typename T> struct expand_operator_less_than_tuple : has_operator_less_than<T> {}; template<typename T> -struct expand_operator_less_than_tuple<std::optional<T>> : has_operator_less_than<T> {}; +struct expand_operator_less_than_tuple<std::optional<T>> : expand_operator_less_than_recursive<T> {}; template<typename T1, typename T2> struct expand_operator_less_than_tuple<std::pair<T1, T2>> : expand_operator_less_than_recursive<T1, T2> {}; template<typename ...T> |