From aec1edfe40f44394f50332d306ee7aa6c86d2222 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 29 May 2024 09:33:39 +0200 Subject: [PATCH] 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 _much_ lighter again, at the expense of qminmax.h now getting , and 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 , and . Task-number: QTBUG-97601 Change-Id: Ied96113f38c1232fef3ec79847ee62f06c68f268 Reviewed-by: Fabian Kosmale (cherry picked from commit b2eb422699118f4ae8370519b4c7bb3fe121beb2) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/global/qttypetraits.h | 189 +++++++++++++++++ src/corelib/global/qtypeinfo.h | 195 ------------------ src/corelib/io/qdebug.h | 1 + src/corelib/kernel/qmetatype.h | 1 + src/corelib/kernel/qproperty.h | 1 + src/corelib/kernel/qpropertyprivate.h | 1 + src/corelib/serialization/qdatastream.h | 1 + src/corelib/tools/qcontiguouscache.h | 1 + src/corelib/tools/qhash.h | 1 + src/corelib/tools/qlist.h | 1 + src/corelib/tools/qmap.h | 1 + src/corelib/tools/qset.h | 1 + src/corelib/tools/qvarlengtharray.h | 1 + src/testlib/qtesttostring.h | 2 + .../corelib/kernel/qvariant/tst_qvariant.cpp | 2 + 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 #include +#include +#include #include #include +#include #if 0 #pragma qt_class(QtTypeTraits) @@ -78,6 +81,192 @@ struct Promoted template using Promoted = typename detail::Promoted::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 +struct is_container : std::false_type {}; +template +struct is_container().begin() != std::declval().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 +struct has_operator_equal : std::false_type {}; +template +struct has_operator_equal() == std::declval()))>> + : std::true_type {}; +QT_WARNING_POP + +// Two forward declarations +template::value> +struct expand_operator_equal_container; +template +struct expand_operator_equal_tuple; + +// the entry point for the public method +template +using expand_operator_equal = expand_operator_equal_container; + +// if T isn't a container check if it's a tuple like object +template +struct expand_operator_equal_container : expand_operator_equal_tuple {}; +// if T::value_type exists, check first T::value_type, then T itself +template +struct expand_operator_equal_container : + std::conjunction< + std::disjunction< + std::is_same, // avoid endless recursion + expand_operator_equal + >, expand_operator_equal_tuple> {}; + +// recursively check the template arguments of a tuple like object +template +using expand_operator_equal_recursive = std::conjunction...>; + +template +struct expand_operator_equal_tuple : has_operator_equal {}; +template +struct expand_operator_equal_tuple> : expand_operator_equal_recursive {}; +template +struct expand_operator_equal_tuple> : expand_operator_equal_recursive {}; +template +struct expand_operator_equal_tuple> : expand_operator_equal_recursive {}; +template +struct expand_operator_equal_tuple> : expand_operator_equal_recursive {}; + +// the same for operator<(), see above for explanations +template +struct has_operator_less_than : std::false_type{}; +template +struct has_operator_less_than() < std::declval()))>> + : std::true_type{}; + +template::value> +struct expand_operator_less_than_container; +template +struct expand_operator_less_than_tuple; + +template +using expand_operator_less_than = expand_operator_less_than_container; + +template +struct expand_operator_less_than_container : expand_operator_less_than_tuple {}; +template +struct expand_operator_less_than_container : + std::conjunction< + std::disjunction< + std::is_same, + expand_operator_less_than + >, expand_operator_less_than_tuple + > {}; + +template +using expand_operator_less_than_recursive = std::conjunction...>; + +template +struct expand_operator_less_than_tuple : has_operator_less_than {}; +template +struct expand_operator_less_than_tuple> : expand_operator_less_than_recursive {}; +template +struct expand_operator_less_than_tuple> : expand_operator_less_than_recursive {}; +template +struct expand_operator_less_than_tuple> : expand_operator_less_than_recursive {}; +template +struct expand_operator_less_than_tuple> : expand_operator_less_than_recursive {}; + +} + +template +struct is_dereferenceable : std::false_type {}; + +template +struct is_dereferenceable().operator->())> > + : std::true_type {}; + +template +inline constexpr bool is_dereferenceable_v = is_dereferenceable::value; + +template +struct has_operator_equal : detail::expand_operator_equal {}; +template +inline constexpr bool has_operator_equal_v = has_operator_equal::value; + +template +using has_operator_equal_container = std::disjunction, QTypeTraits::has_operator_equal>; + +template +struct has_operator_less_than : detail::expand_operator_less_than {}; +template +inline constexpr bool has_operator_less_than_v = has_operator_less_than::value; + +template +using has_operator_less_than_container = std::disjunction, QTypeTraits::has_operator_less_than>; + +template +using compare_eq_result = std::enable_if_t...>, bool>; + +template +using compare_eq_result_container = std::enable_if_t...>, bool>; + +template +using compare_lt_result = std::enable_if_t...>, bool>; + +template +using compare_lt_result_container = std::enable_if_t...>, bool>; + +namespace detail { + +template +const T &const_reference(); +template +T &reference(); + +} + +template +struct has_ostream_operator : std::false_type {}; +template +struct has_ostream_operator() << detail::const_reference())>> + : std::true_type {}; +template +inline constexpr bool has_ostream_operator_v = has_ostream_operator::value; + +template +using has_ostream_operator_container = std::disjunction, QTypeTraits::has_ostream_operator>; + +template +struct has_istream_operator : std::false_type {}; +template +struct has_istream_operator() >> detail::reference())>> + : std::true_type {}; +template +inline constexpr bool has_istream_operator_v = has_istream_operator::value; +template +using has_istream_operator_container = std::disjunction, QTypeTraits::has_istream_operator>; + +template +inline constexpr bool has_stream_operator_v = has_ostream_operator_v && has_istream_operator_v; + } // 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 #include -#include -#include -#include #include QT_BEGIN_NAMESPACE @@ -186,197 +183,5 @@ template class QFlags; template Q_DECLARE_TYPEINFO_BODY(QFlags, 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 -struct is_container : std::false_type {}; -template -struct is_container().begin() != std::declval().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 -struct has_operator_equal : std::false_type {}; -template -struct has_operator_equal() == std::declval()))>> - : std::true_type {}; -QT_WARNING_POP - -// Two forward declarations -template::value> -struct expand_operator_equal_container; -template -struct expand_operator_equal_tuple; - -// the entry point for the public method -template -using expand_operator_equal = expand_operator_equal_container; - -// if T isn't a container check if it's a tuple like object -template -struct expand_operator_equal_container : expand_operator_equal_tuple {}; -// if T::value_type exists, check first T::value_type, then T itself -template -struct expand_operator_equal_container : - std::conjunction< - std::disjunction< - std::is_same, // avoid endless recursion - expand_operator_equal - >, expand_operator_equal_tuple> {}; - -// recursively check the template arguments of a tuple like object -template -using expand_operator_equal_recursive = std::conjunction...>; - -template -struct expand_operator_equal_tuple : has_operator_equal {}; -template -struct expand_operator_equal_tuple> : expand_operator_equal_recursive {}; -template -struct expand_operator_equal_tuple> : expand_operator_equal_recursive {}; -template -struct expand_operator_equal_tuple> : expand_operator_equal_recursive {}; -template -struct expand_operator_equal_tuple> : expand_operator_equal_recursive {}; - -// the same for operator<(), see above for explanations -template -struct has_operator_less_than : std::false_type{}; -template -struct has_operator_less_than() < std::declval()))>> - : std::true_type{}; - -template::value> -struct expand_operator_less_than_container; -template -struct expand_operator_less_than_tuple; - -template -using expand_operator_less_than = expand_operator_less_than_container; - -template -struct expand_operator_less_than_container : expand_operator_less_than_tuple {}; -template -struct expand_operator_less_than_container : - std::conjunction< - std::disjunction< - std::is_same, - expand_operator_less_than - >, expand_operator_less_than_tuple - > {}; - -template -using expand_operator_less_than_recursive = std::conjunction...>; - -template -struct expand_operator_less_than_tuple : has_operator_less_than {}; -template -struct expand_operator_less_than_tuple> : expand_operator_less_than_recursive {}; -template -struct expand_operator_less_than_tuple> : expand_operator_less_than_recursive {}; -template -struct expand_operator_less_than_tuple> : expand_operator_less_than_recursive {}; -template -struct expand_operator_less_than_tuple> : expand_operator_less_than_recursive {}; - -} - -template -struct is_dereferenceable : std::false_type {}; - -template -struct is_dereferenceable().operator->())> > - : std::true_type {}; - -template -inline constexpr bool is_dereferenceable_v = is_dereferenceable::value; - -template -struct has_operator_equal : detail::expand_operator_equal {}; -template -inline constexpr bool has_operator_equal_v = has_operator_equal::value; - -template -using has_operator_equal_container = std::disjunction, QTypeTraits::has_operator_equal>; - -template -struct has_operator_less_than : detail::expand_operator_less_than {}; -template -inline constexpr bool has_operator_less_than_v = has_operator_less_than::value; - -template -using has_operator_less_than_container = std::disjunction, QTypeTraits::has_operator_less_than>; - -template -using compare_eq_result = std::enable_if_t...>, bool>; - -template -using compare_eq_result_container = std::enable_if_t...>, bool>; - -template -using compare_lt_result = std::enable_if_t...>, bool>; - -template -using compare_lt_result_container = std::enable_if_t...>, bool>; - -namespace detail { - -template -const T &const_reference(); -template -T &reference(); - -} - -template -struct has_ostream_operator : std::false_type {}; -template -struct has_ostream_operator() << detail::const_reference())>> - : std::true_type {}; -template -inline constexpr bool has_ostream_operator_v = has_ostream_operator::value; - -template -using has_ostream_operator_container = std::disjunction, QTypeTraits::has_ostream_operator>; - -template -struct has_istream_operator : std::false_type {}; -template -struct has_istream_operator() >> detail::reference())>> - : std::true_type {}; -template -inline constexpr bool has_istream_operator_v = has_istream_operator::value; -template -using has_istream_operator_container = std::disjunction, QTypeTraits::has_istream_operator>; - -template -inline constexpr bool has_stream_operator_v = has_ostream_operator_v && has_istream_operator_v; - -} - - 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 #include +#include #include #include #include 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 #endif #include +#include #include #include 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 #include #include +#include #include #include 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 #include #include +#include #include 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 #include #include +#include #include // 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 #include #include +#include #include #include 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 #include #include +#include #include #include // 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 #include #include +#include #include #include 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 #include #include +#include #include #include 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 #include +#include #include #include 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 #include #include +#include #include #include 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 +#include + #if QT_CONFIG(itemmodel) # include #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 +#include + // don't assume template constexpr inline bool my_is_same_v = false;