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. Pick-to: 6.0 6.1 Fixes: QTBUG-89456 Change-Id: I27305a7cfe050f13a279c07f00bc229c01daa25b Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
f1eccab04e
commit
ce83e56cfe
@ -228,8 +228,8 @@ template <typename, typename = void>
|
||||
struct is_container : std::false_type {};
|
||||
template <typename T>
|
||||
struct is_container<T, std::void_t<
|
||||
std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool>,
|
||||
typename T::value_type
|
||||
typename T::value_type,
|
||||
std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool>
|
||||
>> : std::true_type {};
|
||||
|
||||
|
||||
@ -259,7 +259,11 @@ 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<expand_operator_equal<typename T::value_type>, expand_operator_equal_tuple<T>> {};
|
||||
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>
|
||||
@ -295,7 +299,12 @@ 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<expand_operator_less_than<typename T::value_type>, expand_operator_less_than_tuple<T>> {};
|
||||
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>...>;
|
||||
|
@ -2128,5 +2128,15 @@ void tst_QMetaType::constexprMetaTypeIds()
|
||||
Q_UNUSED(metaType);
|
||||
}
|
||||
|
||||
struct S {
|
||||
using value_type = S; // used to cause compilation error with Qt6
|
||||
int begin();
|
||||
int end();
|
||||
};
|
||||
|
||||
// should not cause a compilation failure
|
||||
// used to cause issues due to S being equal to S::value_type
|
||||
Q_DECLARE_METATYPE(S)
|
||||
|
||||
QTEST_MAIN(tst_QMetaType)
|
||||
#include "tst_qmetatype.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user