summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <[email protected]>2024-05-29 09:33:39 +0200
committerMarc Mutz <[email protected]>2024-06-04 11:31:56 +0000
commitb2eb422699118f4ae8370519b4c7bb3fe121beb2 (patch)
treeab02a3aff638130567cdc04e3852542c12b78f0f
parentcc89c4c76567184b2887952dfe44375ff3ebd28d (diff)
qtypeinfo.h: move QTypeTraits part to qttypetraits.h
Makes sense to collect the stuff in a similarly-named header, and it's not like any of the QTypeTraits stuff was needed for QTypeInfo. Makes #include <qtypeinfo.h> _much_ lighter again, at the expense of qminmax.h now getting <variant>, <tuple> and <optional> instead, but qminmax.h is much easier to avoid in Qt headers (just use the std versions) than qtypeinfo.h. [ChangeLog][QtCore][Potentially Source-Incompatible Changes] The qtypeinfo.h header no longer transitively includes <optional>, <tuple> and <variant>. Task-number: QTBUG-97601 Pick-to: 6.8 Change-Id: Ied96113f38c1232fef3ec79847ee62f06c68f268 Reviewed-by: Fabian Kosmale <[email protected]>
-rw-r--r--src/corelib/global/qttypetraits.h189
-rw-r--r--src/corelib/global/qtypeinfo.h195
-rw-r--r--src/corelib/io/qdebug.h1
-rw-r--r--src/corelib/kernel/qmetatype.h1
-rw-r--r--src/corelib/kernel/qproperty.h1
-rw-r--r--src/corelib/kernel/qpropertyprivate.h1
-rw-r--r--src/corelib/serialization/qdatastream.h1
-rw-r--r--src/corelib/tools/qcontiguouscache.h1
-rw-r--r--src/corelib/tools/qhash.h1
-rw-r--r--src/corelib/tools/qlist.h1
-rw-r--r--src/corelib/tools/qmap.h1
-rw-r--r--src/corelib/tools/qset.h1
-rw-r--r--src/corelib/tools/qvarlengtharray.h1
-rw-r--r--src/testlib/qtesttostring.h2
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp2
15 files changed, 204 insertions, 195 deletions
diff --git a/src/corelib/global/qttypetraits.h b/src/corelib/global/qttypetraits.h
index 35dfad155bf..2cd68c73cbe 100644
--- a/src/corelib/global/qttypetraits.h
+++ b/src/corelib/global/qttypetraits.h
@@ -7,8 +7,11 @@
#include <QtCore/qtconfigmacros.h>
#include <QtCore/qtdeprecationmarkers.h>
+#include <optional>
+#include <tuple>
#include <type_traits>
#include <utility>
+#include <variant>
#if 0
#pragma qt_class(QtTypeTraits)
@@ -78,6 +81,192 @@ struct Promoted
template <typename T, typename U>
using Promoted = typename detail::Promoted<T, U>::type;
+/*
+ The templates below aim to find out whether one can safely instantiate an operator==() or
+ operator<() for a type.
+
+ This is tricky for containers, as most containers have unconstrained comparison operators, even though they
+ rely on the corresponding operators for its content.
+ This is especially true for all of the STL template classes that have a comparison operator defined, and
+ leads to the situation, that the compiler would try to instantiate the operator, and fail if any
+ of its template arguments does not have the operator implemented.
+
+ The code tries to cover the relevant cases for Qt and the STL, by checking (recusrsively) the value_type
+ of a container (if it exists), and checking the template arguments of pair, tuple and variant.
+*/
+namespace detail {
+
+// find out whether T is a conteiner
+// this is required to check the value type of containers for the existence of the comparison operator
+template <typename, typename = void>
+struct is_container : std::false_type {};
+template <typename T>
+struct is_container<T, std::void_t<
+ typename T::value_type,
+ std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool>
+>> : std::true_type {};
+
+
+// Checks the existence of the comparison operator for the class itself
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_FLOAT_COMPARE
+template <typename, typename = void>
+struct has_operator_equal : std::false_type {};
+template <typename T>
+struct has_operator_equal<T, std::void_t<decltype(bool(std::declval<const T&>() == std::declval<const T&>()))>>
+ : std::true_type {};
+QT_WARNING_POP
+
+// Two forward declarations
+template<typename T, bool = is_container<T>::value>
+struct expand_operator_equal_container;
+template<typename T>
+struct expand_operator_equal_tuple;
+
+// the entry point for the public method
+template<typename T>
+using expand_operator_equal = expand_operator_equal_container<T>;
+
+// if T isn't a container check if it's a tuple like object
+template<typename T, bool>
+struct expand_operator_equal_container : expand_operator_equal_tuple<T> {};
+// if T::value_type exists, check first T::value_type, then T itself
+template<typename T>
+struct expand_operator_equal_container<T, true> :
+ std::conjunction<
+ std::disjunction<
+ std::is_same<T, typename T::value_type>, // avoid endless recursion
+ expand_operator_equal<typename T::value_type>
+ >, expand_operator_equal_tuple<T>> {};
+
+// recursively check the template arguments of a tuple like object
+template<typename ...T>
+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>> : 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>
+struct expand_operator_equal_tuple<std::tuple<T...>> : expand_operator_equal_recursive<T...> {};
+template<typename ...T>
+struct expand_operator_equal_tuple<std::variant<T...>> : expand_operator_equal_recursive<T...> {};
+
+// the same for operator<(), see above for explanations
+template <typename, typename = void>
+struct has_operator_less_than : std::false_type{};
+template <typename T>
+struct has_operator_less_than<T, std::void_t<decltype(bool(std::declval<const T&>() < std::declval<const T&>()))>>
+ : std::true_type{};
+
+template<typename T, bool = is_container<T>::value>
+struct expand_operator_less_than_container;
+template<typename T>
+struct expand_operator_less_than_tuple;
+
+template<typename T>
+using expand_operator_less_than = expand_operator_less_than_container<T>;
+
+template<typename T, bool>
+struct expand_operator_less_than_container : expand_operator_less_than_tuple<T> {};
+template<typename T>
+struct expand_operator_less_than_container<T, true> :
+ std::conjunction<
+ std::disjunction<
+ std::is_same<T, typename T::value_type>,
+ expand_operator_less_than<typename T::value_type>
+ >, expand_operator_less_than_tuple<T>
+ > {};
+
+template<typename ...T>
+using expand_operator_less_than_recursive = std::conjunction<expand_operator_less_than<T>...>;
+
+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>> : 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>
+struct expand_operator_less_than_tuple<std::tuple<T...>> : expand_operator_less_than_recursive<T...> {};
+template<typename ...T>
+struct expand_operator_less_than_tuple<std::variant<T...>> : expand_operator_less_than_recursive<T...> {};
+
+}
+
+template<typename T, typename = void>
+struct is_dereferenceable : std::false_type {};
+
+template<typename T>
+struct is_dereferenceable<T, std::void_t<decltype(std::declval<T>().operator->())> >
+ : std::true_type {};
+
+template <typename T>
+inline constexpr bool is_dereferenceable_v = is_dereferenceable<T>::value;
+
+template<typename T>
+struct has_operator_equal : detail::expand_operator_equal<T> {};
+template<typename T>
+inline constexpr bool has_operator_equal_v = has_operator_equal<T>::value;
+
+template <typename Container, typename T>
+using has_operator_equal_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_equal<T>>;
+
+template<typename T>
+struct has_operator_less_than : detail::expand_operator_less_than<T> {};
+template<typename T>
+inline constexpr bool has_operator_less_than_v = has_operator_less_than<T>::value;
+
+template <typename Container, typename T>
+using has_operator_less_than_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_less_than<T>>;
+
+template <typename ...T>
+using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>;
+
+template <typename Container, typename ...T>
+using compare_eq_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal_container<Container, T>...>, bool>;
+
+template <typename ...T>
+using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>;
+
+template <typename Container, typename ...T>
+using compare_lt_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>...>, bool>;
+
+namespace detail {
+
+template<typename T>
+const T &const_reference();
+template<typename T>
+T &reference();
+
+}
+
+template <typename Stream, typename, typename = void>
+struct has_ostream_operator : std::false_type {};
+template <typename Stream, typename T>
+struct has_ostream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() << detail::const_reference<T>())>>
+ : std::true_type {};
+template <typename Stream, typename T>
+inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value;
+
+template <typename Stream, typename Container, typename T>
+using has_ostream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_ostream_operator<Stream, T>>;
+
+template <typename Stream, typename, typename = void>
+struct has_istream_operator : std::false_type {};
+template <typename Stream, typename T>
+struct has_istream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() >> detail::reference<T>())>>
+ : std::true_type {};
+template <typename Stream, typename T>
+inline constexpr bool has_istream_operator_v = has_istream_operator<Stream, T>::value;
+template <typename Stream, typename Container, typename T>
+using has_istream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_istream_operator<Stream, T>>;
+
+template <typename Stream, typename T>
+inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>;
+
} // namespace QTypeTraits
QT_END_NAMESPACE
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 255a2b33c61..e9dfbc34a4f 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -8,9 +8,6 @@
#include <QtCore/qcompilerdetection.h>
#include <QtCore/qcontainerfwd.h>
-#include <variant>
-#include <optional>
-#include <tuple>
#include <type_traits>
QT_BEGIN_NAMESPACE
@@ -186,197 +183,5 @@ template<typename T> class QFlags;
template<typename T>
Q_DECLARE_TYPEINFO_BODY(QFlags<T>, Q_PRIMITIVE_TYPE);
-namespace QTypeTraits
-{
-
-/*
- The templates below aim to find out whether one can safely instantiate an operator==() or
- operator<() for a type.
-
- This is tricky for containers, as most containers have unconstrained comparison operators, even though they
- rely on the corresponding operators for its content.
- This is especially true for all of the STL template classes that have a comparison operator defined, and
- leads to the situation, that the compiler would try to instantiate the operator, and fail if any
- of its template arguments does not have the operator implemented.
-
- The code tries to cover the relevant cases for Qt and the STL, by checking (recusrsively) the value_type
- of a container (if it exists), and checking the template arguments of pair, tuple and variant.
-*/
-namespace detail {
-
-// find out whether T is a conteiner
-// this is required to check the value type of containers for the existence of the comparison operator
-template <typename, typename = void>
-struct is_container : std::false_type {};
-template <typename T>
-struct is_container<T, std::void_t<
- typename T::value_type,
- std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool>
->> : std::true_type {};
-
-
-// Checks the existence of the comparison operator for the class itself
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_FLOAT_COMPARE
-template <typename, typename = void>
-struct has_operator_equal : std::false_type {};
-template <typename T>
-struct has_operator_equal<T, std::void_t<decltype(bool(std::declval<const T&>() == std::declval<const T&>()))>>
- : std::true_type {};
-QT_WARNING_POP
-
-// Two forward declarations
-template<typename T, bool = is_container<T>::value>
-struct expand_operator_equal_container;
-template<typename T>
-struct expand_operator_equal_tuple;
-
-// the entry point for the public method
-template<typename T>
-using expand_operator_equal = expand_operator_equal_container<T>;
-
-// if T isn't a container check if it's a tuple like object
-template<typename T, bool>
-struct expand_operator_equal_container : expand_operator_equal_tuple<T> {};
-// if T::value_type exists, check first T::value_type, then T itself
-template<typename T>
-struct expand_operator_equal_container<T, true> :
- std::conjunction<
- std::disjunction<
- std::is_same<T, typename T::value_type>, // avoid endless recursion
- expand_operator_equal<typename T::value_type>
- >, expand_operator_equal_tuple<T>> {};
-
-// recursively check the template arguments of a tuple like object
-template<typename ...T>
-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>> : 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>
-struct expand_operator_equal_tuple<std::tuple<T...>> : expand_operator_equal_recursive<T...> {};
-template<typename ...T>
-struct expand_operator_equal_tuple<std::variant<T...>> : expand_operator_equal_recursive<T...> {};
-
-// the same for operator<(), see above for explanations
-template <typename, typename = void>
-struct has_operator_less_than : std::false_type{};
-template <typename T>
-struct has_operator_less_than<T, std::void_t<decltype(bool(std::declval<const T&>() < std::declval<const T&>()))>>
- : std::true_type{};
-
-template<typename T, bool = is_container<T>::value>
-struct expand_operator_less_than_container;
-template<typename T>
-struct expand_operator_less_than_tuple;
-
-template<typename T>
-using expand_operator_less_than = expand_operator_less_than_container<T>;
-
-template<typename T, bool>
-struct expand_operator_less_than_container : expand_operator_less_than_tuple<T> {};
-template<typename T>
-struct expand_operator_less_than_container<T, true> :
- std::conjunction<
- std::disjunction<
- std::is_same<T, typename T::value_type>,
- expand_operator_less_than<typename T::value_type>
- >, expand_operator_less_than_tuple<T>
- > {};
-
-template<typename ...T>
-using expand_operator_less_than_recursive = std::conjunction<expand_operator_less_than<T>...>;
-
-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>> : 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>
-struct expand_operator_less_than_tuple<std::tuple<T...>> : expand_operator_less_than_recursive<T...> {};
-template<typename ...T>
-struct expand_operator_less_than_tuple<std::variant<T...>> : expand_operator_less_than_recursive<T...> {};
-
-}
-
-template<typename T, typename = void>
-struct is_dereferenceable : std::false_type {};
-
-template<typename T>
-struct is_dereferenceable<T, std::void_t<decltype(std::declval<T>().operator->())> >
- : std::true_type {};
-
-template <typename T>
-inline constexpr bool is_dereferenceable_v = is_dereferenceable<T>::value;
-
-template<typename T>
-struct has_operator_equal : detail::expand_operator_equal<T> {};
-template<typename T>
-inline constexpr bool has_operator_equal_v = has_operator_equal<T>::value;
-
-template <typename Container, typename T>
-using has_operator_equal_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_equal<T>>;
-
-template<typename T>
-struct has_operator_less_than : detail::expand_operator_less_than<T> {};
-template<typename T>
-inline constexpr bool has_operator_less_than_v = has_operator_less_than<T>::value;
-
-template <typename Container, typename T>
-using has_operator_less_than_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_less_than<T>>;
-
-template <typename ...T>
-using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>;
-
-template <typename Container, typename ...T>
-using compare_eq_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal_container<Container, T>...>, bool>;
-
-template <typename ...T>
-using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>;
-
-template <typename Container, typename ...T>
-using compare_lt_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>...>, bool>;
-
-namespace detail {
-
-template<typename T>
-const T &const_reference();
-template<typename T>
-T &reference();
-
-}
-
-template <typename Stream, typename, typename = void>
-struct has_ostream_operator : std::false_type {};
-template <typename Stream, typename T>
-struct has_ostream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() << detail::const_reference<T>())>>
- : std::true_type {};
-template <typename Stream, typename T>
-inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value;
-
-template <typename Stream, typename Container, typename T>
-using has_ostream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_ostream_operator<Stream, T>>;
-
-template <typename Stream, typename, typename = void>
-struct has_istream_operator : std::false_type {};
-template <typename Stream, typename T>
-struct has_istream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() >> detail::reference<T>())>>
- : std::true_type {};
-template <typename Stream, typename T>
-inline constexpr bool has_istream_operator_v = has_istream_operator<Stream, T>::value;
-template <typename Stream, typename Container, typename T>
-using has_istream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_istream_operator<Stream, T>>;
-
-template <typename Stream, typename T>
-inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>;
-
-}
-
-
QT_END_NAMESPACE
#endif // QTYPEINFO_H
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 4797bcd169f..44c3dea804b 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -11,6 +11,7 @@
#include <QtCore/qcontainerfwd.h>
#include <QtCore/qtextstream.h>
+#include <QtCore/qttypetraits.h>
#include <QtCore/qtypes.h>
#include <QtCore/qstring.h>
#include <QtCore/qcontiguouscache.h>
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 12a67aef584..1e944660c61 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -18,6 +18,7 @@
#include <QtCore/qobjectdefs.h>
#endif
#include <QtCore/qscopeguard.h>
+#include <QtCore/qttypetraits.h>
#include <array>
#include <new>
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h
index 0373867a661..8c4b13cf5e8 100644
--- a/src/corelib/kernel/qproperty.h
+++ b/src/corelib/kernel/qproperty.h
@@ -7,6 +7,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qstring.h>
+#include <QtCore/qttypetraits.h>
#include <QtCore/qbindingstorage.h>
#include <type_traits>
diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h
index a8456721d05..c4a73f2c912 100644
--- a/src/corelib/kernel/qpropertyprivate.h
+++ b/src/corelib/kernel/qpropertyprivate.h
@@ -19,6 +19,7 @@
#include <QtCore/qtaggedpointer.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qcontainerfwd.h>
+#include <QtCore/qttypetraits.h>
#include <functional>
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index cf37df71d75..e094d76c13e 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -8,6 +8,7 @@
#include <QtCore/qiodevicebase.h>
#include <QtCore/qcontainerfwd.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qttypetraits.h>
#include <iterator> // std::distance(), std::next()
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
index c01dbb9390f..e3f98c30de6 100644
--- a/src/corelib/tools/qcontiguouscache.h
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -8,6 +8,7 @@
#include <QtCore/qassert.h>
#include <QtCore/qtclasshelpermacros.h>
#include <QtCore/qtcoreexports.h>
+#include <QtCore/qttypetraits.h>
#include <QtCore/qtypeinfo.h>
#include <climits>
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index e7cd4123fb4..9cc6fbf30bc 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -11,6 +11,7 @@
#include <QtCore/qiterator.h>
#include <QtCore/qlist.h>
#include <QtCore/qrefcount.h>
+#include <QtCore/qttypetraits.h>
#include <initializer_list>
#include <functional> // for std::hash
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 89e0e3f380f..1cced5acc2d 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -11,6 +11,7 @@
#include <QtCore/qiterator.h>
#include <QtCore/qcontainertools_impl.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qttypetraits.h>
#include <functional>
#include <limits>
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 7ee0be1e519..326ae7d8a51 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -12,6 +12,7 @@
#include <QtCore/qpair.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qshareddata_impl.h>
+#include <QtCore/qttypetraits.h>
#include <functional>
#include <initializer_list>
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index 7330b5e91cc..6eaeb8fc417 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -6,6 +6,7 @@
#include <QtCore/qhash.h>
#include <QtCore/qcontainertools_impl.h>
+#include <QtCore/qttypetraits.h>
#include <initializer_list>
#include <iterator>
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index 0a579bf4873..78d5a276277 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -14,6 +14,7 @@
#include <QtCore/qalgorithms.h>
#include <QtCore/qcontainertools_impl.h>
#include <QtCore/qhashfunctions.h>
+#include <QtCore/qttypetraits.h>
#include <algorithm>
#include <initializer_list>
diff --git a/src/testlib/qtesttostring.h b/src/testlib/qtesttostring.h
index 18262332ba3..a1ee4f69258 100644
--- a/src/testlib/qtesttostring.h
+++ b/src/testlib/qtesttostring.h
@@ -7,6 +7,8 @@
#include <QtTest/qttestglobal.h>
+#include <QtCore/qttypetraits.h>
+
#if QT_CONFIG(itemmodel)
# include <QtCore/qabstractitemmodel.h>
#endif
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index a8e2c7bda37..d79e0e82f8a 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -5,6 +5,8 @@
#include <qvariant.h>
+#include <QtCore/qttypetraits.h>
+
// don't assume <type_traits>
template <typename T, typename U>
constexpr inline bool my_is_same_v = false;