summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qtypeinfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/global/qtypeinfo.h')
-rw-r--r--src/corelib/global/qtypeinfo.h42
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>