diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-07-12 11:17:21 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-07-14 17:06:47 +0200 |
commit | ca54b741d6edda24773137aacee229db31dd3585 (patch) | |
tree | 11625d145a4350e620e0572972ab94710e2d3ef3 /src | |
parent | 8cdaeb26552313e7b9d67fa062a3d9ff597c2e06 (diff) |
qtypeinfo: Improve container check
Smart pointers like QSharedPointer<T> do have a value_type, but their
equality does not depend on T being comparable. Therefore, instead of
simply checking for T::value_type, test for a few other container
requirements.
This also required to add an additional check for std::optional, as that
one has an unconstrained operator== on MSVC.
Change-Id: Iefd048f7aa360f4713ecd79f80acd7dae72ee18c
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/global/qtypeinfo.h | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 9b85a41266..be21526339 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -41,6 +41,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qcontainerfwd.h> #include <variant> +#include <optional> #ifndef QTYPEINFO_H #define QTYPEINFO_H @@ -342,12 +343,16 @@ namespace QTypeTraits */ namespace detail { -// find out whether T has a value_type typedef +// 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 has_value_type : std::false_type {}; +struct is_container : std::false_type {}; template <typename T> -struct has_value_type<T, std::void_t<typename T::value_type>> : std::true_type {}; +struct is_container<T, std::void_t< + std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool>, + typename T::value_type +>> : std::true_type {}; + // Checks the existence of the comparison operator for the class itself template <typename, typename = void> @@ -357,7 +362,7 @@ struct has_operator_equal<T, std::void_t<decltype(bool(std::declval<const T&>() : std::true_type {}; // Two forward declarations -template<typename T, bool = has_value_type<T>::value> +template<typename T, bool = is_container<T>::value> struct expand_operator_equal_container; template<typename T> struct expand_operator_equal_tuple; @@ -366,7 +371,7 @@ struct expand_operator_equal_tuple; template<typename T> using expand_operator_equal = expand_operator_equal_container<T>; -// if T doesn't have a value_type member check if it's a tuple like object +// 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 @@ -380,6 +385,8 @@ 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> {}; template<typename T1, typename T2> struct expand_operator_equal_tuple<std::pair<T1, T2>> : expand_operator_equal_recursive<T1, T2> {}; template<typename ...T> @@ -394,7 +401,7 @@ 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 = has_value_type<T>::value> +template<typename T, bool = is_container<T>::value> struct expand_operator_less_than_container; template<typename T> struct expand_operator_less_than_tuple; |