Skip to content

Commit

Permalink
libstdc++: Fix std::indirectly_readable ambiguity [LWG 3446]
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jwakely committed Aug 24, 2020
1 parent a0e6f05 commit 186aa63
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 2 deletions.
30 changes: 28 additions & 2 deletions libstdc++-v3/include/bits/iterator_concepts.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp> requires is_object_v<_Tp>
struct __cond_value_type<_Tp>
{ using value_type = remove_cv_t<_Tp>; };

template<typename _Tp>
concept __has_member_value_type
= requires { typename _Tp::value_type; };

template<typename _Tp>
concept __has_member_element_type
= requires { typename _Tp::element_type; };

} // namespace __detail

template<typename> struct indirectly_readable_traits { };
Expand All @@ -238,16 +247,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: indirectly_readable_traits<_Iter>
{ };

template<typename _Tp> requires requires { typename _Tp::value_type; }
template<__detail::__has_member_value_type _Tp>
struct indirectly_readable_traits<_Tp>
: __detail::__cond_value_type<typename _Tp::value_type>
{ };

template<typename _Tp> requires requires { typename _Tp::element_type; }
template<__detail::__has_member_element_type _Tp>
struct indirectly_readable_traits<_Tp>
: __detail::__cond_value_type<typename _Tp::element_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<typename _Tp::element_type>,
remove_cv_t<typename _Tp::value_type>>
struct indirectly_readable_traits<_Tp>
: __detail::__cond_value_type<typename _Tp::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<typename _Tp>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,29 @@ struct J
// iterator_traits<J> matches constrained specialization in the library,
// so use its value_type.
static_assert( check_alias<J, int> );

struct I2
{
using element_type = int;
};
// iterator_traits<I2> is not specialized, and no standard specialization
// matches, so use indirectly_readable_traits.
static_assert( check_alias<I2, std::indirectly_readable_traits<I2>::value_type> );

// LWG 3446
struct I3
{
using value_type = long;
using element_type = const long;
};
// iterator_traits<I3> is not specialized, and no standard specialization
// matches, so use indirectly_readable_traits.
static_assert( check_alias<I3, std::indirectly_readable_traits<I3>::value_type> );

// Correction to LWG 3446
struct I4
{
using value_type = int;
using element_type = long;
};
static_assert( ! has_alias<I4> );

0 comments on commit 186aa63

Please sign in to comment.