From 186aa6304570e15065f31482e9c27326a3a6679f Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 24 Aug 2020 16:18:31 +0100 Subject: [PATCH] libstdc++: Fix std::indirectly_readable ambiguity [LWG 3446] This implements the proposed resolution of LWG 3446. I'm also adding another new constrained specialization which isn't proposed by 3446, to resolve the ambiguity when a type has both value_type and element_type but denoting different types. libstdc++-v3/ChangeLog: * include/bits/iterator_concepts.h (indirectly_readable): Add partial specializations to resolve ambiguities (LWG 3446). * testsuite/24_iterators/associated_types/readable.traits.cc: Check types with both value_type and element_type. --- libstdc++-v3/include/bits/iterator_concepts.h | 30 +++++++++++++++++-- .../associated_types/readable.traits.cc | 26 ++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index bd6660c5f22..a568f2ab825 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -220,6 +220,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template requires is_object_v<_Tp> struct __cond_value_type<_Tp> { using value_type = remove_cv_t<_Tp>; }; + + template + concept __has_member_value_type + = requires { typename _Tp::value_type; }; + + template + concept __has_member_element_type + = requires { typename _Tp::element_type; }; + } // namespace __detail template struct indirectly_readable_traits { }; @@ -238,16 +247,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : indirectly_readable_traits<_Iter> { }; - template requires requires { typename _Tp::value_type; } + template<__detail::__has_member_value_type _Tp> struct indirectly_readable_traits<_Tp> : __detail::__cond_value_type { }; - template requires requires { typename _Tp::element_type; } + template<__detail::__has_member_element_type _Tp> struct indirectly_readable_traits<_Tp> : __detail::__cond_value_type { }; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3446. indirectly_readable_traits ambiguity for types with both [...] + template<__detail::__has_member_value_type _Tp> + requires __detail::__has_member_element_type<_Tp> + && same_as, + remove_cv_t> + struct indirectly_readable_traits<_Tp> + : __detail::__cond_value_type + { }; + + // LWG 3446 doesn't add this, but it's needed for the case where + // value_type and element_type are both present, but not the same type. + template<__detail::__has_member_value_type _Tp> + requires __detail::__has_member_element_type<_Tp> + struct indirectly_readable_traits<_Tp> + { }; + namespace __detail { template diff --git a/libstdc++-v3/testsuite/24_iterators/associated_types/readable.traits.cc b/libstdc++-v3/testsuite/24_iterators/associated_types/readable.traits.cc index b503b0cdc1e..3c9c3927153 100644 --- a/libstdc++-v3/testsuite/24_iterators/associated_types/readable.traits.cc +++ b/libstdc++-v3/testsuite/24_iterators/associated_types/readable.traits.cc @@ -141,3 +141,29 @@ struct J // iterator_traits matches constrained specialization in the library, // so use its value_type. static_assert( check_alias ); + +struct I2 +{ + using element_type = int; +}; +// iterator_traits is not specialized, and no standard specialization +// matches, so use indirectly_readable_traits. +static_assert( check_alias::value_type> ); + +// LWG 3446 +struct I3 +{ + using value_type = long; + using element_type = const long; +}; +// iterator_traits is not specialized, and no standard specialization +// matches, so use indirectly_readable_traits. +static_assert( check_alias::value_type> ); + +// Correction to LWG 3446 +struct I4 +{ + using value_type = int; + using element_type = long; +}; +static_assert( ! has_alias ); -- 2.30.2