[PATCH 3/4] libstdc++: Implement ranges::chunk_view from P2442R1
Jonathan Wakely
jwakely@redhat.com
Tue Sep 13 11:10:42 GMT 2022
On Mon, 12 Sept 2022 at 17:48, Patrick Palka via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> This also implements the LWG 3707, 3710 and 3712 changes to chunk_view.
> +
> + template<view _Vp>
> + requires input_range<_Vp>
> + class chunk_view<_Vp>::_OuterIter
> + {
> + chunk_view* _M_parent;
> +
> + constexpr explicit
> + _OuterIter(chunk_view& __parent)
This can be noexcept.
> + : _M_parent(std::__addressof(__parent))
> + { }
> +
> + friend chunk_view;
> +
> + public:
> + using iterator_concept = input_iterator_tag;
> + using difference_type = range_difference_t<_Vp>;
> +
> + struct value_type;
> +
> + _OuterIter(_OuterIter&&) = default;
> + _OuterIter& operator=(_OuterIter&&) = default;
> +
> + constexpr value_type
> + operator*() const
> + {
> + __glibcxx_assert(*this != default_sentinel);
> + return value_type(*_M_parent);
> + }
> +
> + constexpr _OuterIter&
> + operator++()
> + {
> + __glibcxx_assert(*this != default_sentinel);
> + ranges::advance(*_M_parent->_M_current, _M_parent->_M_remainder,
> + ranges::end(_M_parent->_M_base));
> + _M_parent->_M_remainder = _M_parent->_M_n;
> + return *this;
> + }
> +
> + constexpr void
> + operator++(int)
> + { ++*this; }
> +
> + friend constexpr bool
> + operator==(const _OuterIter& __x, default_sentinel_t)
> + {
> + return *__x._M_parent->_M_current == ranges::end(__x._M_parent->_M_base)
> + && __x._M_parent->_M_remainder != 0;
> + }
> +
> + friend constexpr difference_type
> + operator-(default_sentinel_t, const _OuterIter& __x)
> + requires sized_sentinel_for<sentinel_t<_Vp>, iterator_t<_Vp>>
> + {
> + const auto __dist = ranges::end(__x._M_parent->_M_base) - *__x._M_parent->_M_current;
> +
> + if (__dist < __x._M_parent->_M_remainder)
> + return __dist == 0 ? 0 : 1;
> +
> + return 1 + __detail::__div_ceil(__dist - __x._M_parent->_M_remainder,
> + __x._M_parent->_M_n);
> + }
> +
> + friend constexpr difference_type
> + operator-(const _OuterIter& __x, default_sentinel_t __y)
> + requires sized_sentinel_for<sentinel_t<_Vp>, iterator_t<_Vp>>
> + { return -(__y - __x); }
> + };
> +
> + template<view _Vp>
> + requires input_range<_Vp>
> + struct chunk_view<_Vp>::_OuterIter::value_type : view_interface<value_type>
> + {
> + private:
> + chunk_view* _M_parent;
> +
> + constexpr explicit
> + value_type(chunk_view& __parent)
And this.
> + : _M_parent(std::__addressof(__parent))
> + { }
> +
> + friend _OuterIter;
> +
> + template<view _Vp>
> + requires input_range<_Vp>
> + class chunk_view<_Vp>::_InnerIter
> + {
> + chunk_view* _M_parent;
> +
> + constexpr explicit
> + _InnerIter(chunk_view& __parent) noexcept
And this already is, so that's nice.
> + : _M_parent(std::__addressof(__parent))
> + { }
> +
> + friend _OuterIter::value_type;
> +
> + public:
> + using iterator_concept = input_iterator_tag;
> + using difference_type = range_difference_t<_Vp>;
> + using value_type = range_value_t<_Vp>;
> +
> + _InnerIter(_InnerIter&&) = default;
> + _InnerIter& operator=(_InnerIter&&) = default;
> +
> + constexpr const iterator_t<_Vp>&
> + base() const &
> + { return *_M_parent->_M_current; }
> +
> + constexpr range_reference_t<_Vp>
> + operator*() const
> + {
> + __glibcxx_assert(*this != default_sentinel);
> + return **_M_parent->_M_current;
> + }
> +
> + constexpr _InnerIter&
> + operator++()
> + {
> + __glibcxx_assert(*this != default_sentinel);
> + ++*_M_parent->_M_current;
> + if (*_M_parent->_M_current == ranges::end(_M_parent->_M_base))
> + _M_parent->_M_remainder = 0;
> + else
> + --_M_parent->_M_remainder;
> + return *this;
> + }
> +
> + constexpr void
> + operator++(int)
> + { ++*this; }
> +
> + friend constexpr bool
> + operator==(const _InnerIter& __x, default_sentinel_t)
noexcept
OK with those tweaks.
More information about the Libstdc++
mailing list