From 687685f64928ed69b2161f9f2ff4f303bec04967 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Tue, 23 Mar 2021 22:29:53 +0100 Subject: QTypeInfo: Handle T::value_type being equal to T Fix operator checks for containers whose value_type equals themselves. It does not make sense to recurse on value_type in that case. Thanks to std::disjunction having short-circuiting semantics, we can avoid that issue by checking first whether T is T::value_type. As a drive-by, check for value_type typedef before checking for begin/end in is_container. This works around an issue in gcc <= 8.1, which fails to correctly SFINAE the case where begin and end are private methods. Fixes: QTBUG-89456 Change-Id: I27305a7cfe050f13a279c07f00bc229c01daa25b Reviewed-by: Ulf Hermann (cherry picked from commit ce83e56cfeb2806181ec1daade9690f4c90b901c) Reviewed-by: Thiago Macieira --- src/corelib/global/qtypeinfo.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index e5914414f2..ec43586765 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -227,8 +227,8 @@ template struct is_container : std::false_type {}; template struct is_container().begin() != std::declval().end()), bool>, - typename T::value_type + typename T::value_type, + std::is_convertible().begin() != std::declval().end()), bool> >> : std::true_type {}; @@ -258,7 +258,11 @@ 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, expand_operator_equal_tuple> {}; + 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 @@ -294,7 +298,12 @@ template struct expand_operator_less_than_container : expand_operator_less_than_tuple {}; template struct expand_operator_less_than_container : - std::conjunction, expand_operator_less_than_tuple> {}; + 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...>; -- cgit v1.2.3