libstdc++: Implement P1994R1 changes to ranges::elements_view

The example from the paper doesn't compile without the proposed
resolution for LWG 3406, so we'll add a testcase for this once the
proposed resolution is implemented.

libstdc++-v3/ChangeLog:

	* include/std/ranges (elements_view::end): Replace these two
	overloads with four new overloads.
	(elements_view::_Iterator::operator==): Remove.
	(elements_view::_Iterator::operator-): Likewise.
	(elements_view::_Sentinel): Define.
This commit is contained in:
Patrick Palka 2020-08-26 21:49:51 -04:00
parent 57ea089421
commit 97ab5daa6c

View file

@ -3366,12 +3366,20 @@ namespace views
{ return _Iterator<true>(ranges::begin(_M_base)); }
constexpr auto
end() requires (!__detail::__simple_view<_Vp>)
{ return ranges::end(_M_base); }
end()
{ return _Sentinel<false>{ranges::end(_M_base)}; }
constexpr auto
end() const requires __detail::__simple_view<_Vp>
{ return ranges::end(_M_base); }
end() requires common_range<_Vp>
{ return _Iterator<false>{ranges::end(_M_base)}; }
constexpr auto
end() const requires range<const _Vp>
{ return _Sentinel<true>{ranges::end(_M_base)}; }
constexpr auto
end() const requires common_range<const _Vp>
{ return _Iterator<true>{ranges::end(_M_base)}; }
constexpr auto
size() requires sized_range<_Vp>
@ -3382,6 +3390,9 @@ namespace views
{ return ranges::size(_M_base); }
private:
template<bool _Const>
struct _Sentinel;
template<bool _Const>
struct _Iterator
{
@ -3484,10 +3495,6 @@ namespace views
requires equality_comparable<iterator_t<_Base>>
{ return __x._M_current == __y._M_current; }
friend constexpr bool
operator==(const _Iterator& __x, const sentinel_t<_Base>& __y)
{ return __x._M_current == __y; }
friend constexpr bool
operator<(const _Iterator& __x, const _Iterator& __y)
requires random_access_range<_Base>
@ -3536,15 +3543,54 @@ namespace views
requires random_access_range<_Base>
{ return __x._M_current - __y._M_current; }
friend constexpr difference_type
operator-(const _Iterator<_Const>& __x, const sentinel_t<_Base>& __y)
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
{ return __x._M_current - __y; }
friend _Sentinel<_Const>;
};
friend constexpr difference_type
operator-(const sentinel_t<_Base>& __x, const _Iterator<_Const>& __y)
template<bool _Const>
struct _Sentinel
{
private:
constexpr bool
_M_equal(const _Iterator<_Const>& __x) const
{ return __x._M_current == _M_end; }
using _Base = __detail::__maybe_const_t<_Const, _Vp>;
sentinel_t<_Base> _M_end = sentinel_t<_Base>();
public:
_Sentinel() = default;
constexpr explicit
_Sentinel(sentinel_t<_Base> __end)
: _M_end(std::move(__end))
{ }
constexpr
_Sentinel(_Sentinel<!_Const> __other)
requires _Const
&& convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>>
: _M_end(std::move(__other._M_end))
{ }
constexpr sentinel_t<_Base>
base() const
{ return _M_end; }
friend constexpr bool
operator==(const _Iterator<_Const>& __x, const _Sentinel& __y)
{ return __y._M_equal(__x); }
friend constexpr range_difference_t<_Base>
operator-(const _Iterator<_Const>& __x, const _Sentinel& __y)
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
{ return -(__y - __x); }
{ return __x._M_current - __y._M_end; }
friend constexpr range_difference_t<_Base>
operator-(const _Sentinel& __x, const _Iterator<_Const>& __y)
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
{ return __x._M_end - __y._M_current; }
friend _Sentinel<!_Const>;
};
_Vp _M_base = _Vp();