Re: [PATCH 2/2] libstdc++: Implement ranges::adjacent_transform_view from P2321R2
On Tue, 30 Aug 2022 at 18:14, Patrick Palka via Libstdc++ wrote: > > Tested on x86_64-pc-linux-gnu, does this look OK for trunk? OK > > libstdc++-v3/ChangeLog: > > * include/std/ranges (__detail::__unarize): Define. > (adjacent_view::_Iterator): Befriend adjacent_transform_view. > (adjacent_transform_view): Define. > (adjacent_transform_view::_Iterator): Define. > (adjacent_transform_view::_Sentinel): Define. > (views::__detail::__can_adjacent_transform_view): Define. > (views::_AdjacentTransform): Define. > (views::adjacent_transform): Define. > (views::pairwise): Define. > * testsuite/std/ranges/adaptors/adjacent_transform/1.cc: New test. > --- > libstdc++-v3/include/std/ranges | 342 ++ > .../ranges/adaptors/adjacent_transform/1.cc | 106 ++ > 2 files changed, 448 insertions(+) > create mode 100644 > libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc > > diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges > index 4fb879a088c..3a7f0545030 100644 > --- a/libstdc++-v3/include/std/ranges > +++ b/libstdc++-v3/include/std/ranges > @@ -5158,6 +5158,20 @@ namespace views::__adaptor > // Yields tuple<_Tp, ..., _Tp> with _Nm elements. > template >using __repeated_tuple = > decltype(std::tuple_cat(std::declval>())); > + > +// For a functor F that takes N arguments, the expression > declval<__unarize>(x) > +// is equivalent to declval(x, ..., x). > +template > + struct __unarize > + { > + template > + static invoke_result_t<_Fp, _Ts...> > + __tuple_apply(const tuple<_Ts...>&); // not defined > + > + template > + decltype(__tuple_apply(std::declval<__repeated_tuple<_Tp, _Nm>>())) > + operator()(_Tp&&); // not defined > + }; >} > >template > @@ -5205,6 +5219,13 @@ namespace views::__adaptor > > friend class adjacent_view; > > +template > + requires view<_Wp> && (_Mm > 0) && is_object_v<_Fp> > +&& regular_invocable<__detail::__unarize<_Fp&, _Mm>, > range_reference_t<_Wp>> > +&& > std::__detail::__can_reference, > + > range_reference_t<_Wp>>> > + friend class adjacent_transform_view; > + >public: > using iterator_category = input_iterator_tag; > using iterator_concept = decltype(_S_iter_concept()); > @@ -5440,6 +5461,327 @@ namespace views::__adaptor > > inline constexpr auto pairwise = adjacent<2>; >} > + > + template > + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> > + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, > range_reference_t<_Vp>> > + && > std::__detail::__can_reference, > + > range_reference_t<_Vp>>> > + class adjacent_transform_view : public > view_interface> > + { > +[[no_unique_address]] __detail::__box<_Fp> _M_fun; > +adjacent_view<_Vp, _Nm> _M_inner; > + > +using _InnerView = adjacent_view<_Vp, _Nm>; > + > +template > + using _InnerIter = iterator_t<__detail::__maybe_const_t<_Const, > _InnerView>>; > + > +template > + using _InnerSent = sentinel_t<__detail::__maybe_const_t<_Const, > _InnerView>>; > + > +template class _Iterator; > +template class _Sentinel; > + > + public: > +adjacent_transform_view() = default; > + > +constexpr explicit > +adjacent_transform_view(_Vp __base, _Fp __fun) > + : _M_fun(std::move(__fun)), _M_inner(std::move(__base)) > +{ } > + > +constexpr auto > +begin() > +{ return _Iterator(*this, _M_inner.begin()); } > + > +constexpr auto > +begin() const > + requires range > + && regular_invocable<__detail::__unarize, > +range_reference_t> > +{ return _Iterator(*this, _M_inner.begin()); } > + > +constexpr auto > +end() > +{ > + if constexpr (common_range<_InnerView>) > +return _Iterator(*this, _M_inner.end()); > + else > +return _Sentinel(_M_inner.end()); > +} > + > +constexpr auto > +end() const > + requires range > + && regular_invocable<__detail::__unarize, > +range_reference_t> > +{ > + if constexpr (common_range) > +return _Iterator(*this, _M_inner.end()); > + else > +return _Sentinel(_M_inner.end()); > +} > + > +constexpr auto > +size() requires sized_range<_InnerView> > +{ return _M_inner.size(); } > + > +constexpr auto > +size() const requires sized_range > +{ return _M_inner.size(); } > + }; > + > + template > + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> > + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, > range_reference_t<_Vp>> > + && > std::__detail::__can_reference, > +
[PATCH 2/2] libstdc++: Implement ranges::adjacent_transform_view from P2321R2
Tested on x86_64-pc-linux-gnu, does this look OK for trunk? libstdc++-v3/ChangeLog: * include/std/ranges (__detail::__unarize): Define. (adjacent_view::_Iterator): Befriend adjacent_transform_view. (adjacent_transform_view): Define. (adjacent_transform_view::_Iterator): Define. (adjacent_transform_view::_Sentinel): Define. (views::__detail::__can_adjacent_transform_view): Define. (views::_AdjacentTransform): Define. (views::adjacent_transform): Define. (views::pairwise): Define. * testsuite/std/ranges/adaptors/adjacent_transform/1.cc: New test. --- libstdc++-v3/include/std/ranges | 342 ++ .../ranges/adaptors/adjacent_transform/1.cc | 106 ++ 2 files changed, 448 insertions(+) create mode 100644 libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 4fb879a088c..3a7f0545030 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -5158,6 +5158,20 @@ namespace views::__adaptor // Yields tuple<_Tp, ..., _Tp> with _Nm elements. template using __repeated_tuple = decltype(std::tuple_cat(std::declval>())); + +// For a functor F that takes N arguments, the expression declval<__unarize>(x) +// is equivalent to declval(x, ..., x). +template + struct __unarize + { + template + static invoke_result_t<_Fp, _Ts...> + __tuple_apply(const tuple<_Ts...>&); // not defined + + template + decltype(__tuple_apply(std::declval<__repeated_tuple<_Tp, _Nm>>())) + operator()(_Tp&&); // not defined + }; } template @@ -5205,6 +5219,13 @@ namespace views::__adaptor friend class adjacent_view; +template + requires view<_Wp> && (_Mm > 0) && is_object_v<_Fp> +&& regular_invocable<__detail::__unarize<_Fp&, _Mm>, range_reference_t<_Wp>> +&& std::__detail::__can_reference, + range_reference_t<_Wp>>> + friend class adjacent_transform_view; + public: using iterator_category = input_iterator_tag; using iterator_concept = decltype(_S_iter_concept()); @@ -5440,6 +5461,327 @@ namespace views::__adaptor inline constexpr auto pairwise = adjacent<2>; } + + template + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference, + range_reference_t<_Vp>>> + class adjacent_transform_view : public view_interface> + { +[[no_unique_address]] __detail::__box<_Fp> _M_fun; +adjacent_view<_Vp, _Nm> _M_inner; + +using _InnerView = adjacent_view<_Vp, _Nm>; + +template + using _InnerIter = iterator_t<__detail::__maybe_const_t<_Const, _InnerView>>; + +template + using _InnerSent = sentinel_t<__detail::__maybe_const_t<_Const, _InnerView>>; + +template class _Iterator; +template class _Sentinel; + + public: +adjacent_transform_view() = default; + +constexpr explicit +adjacent_transform_view(_Vp __base, _Fp __fun) + : _M_fun(std::move(__fun)), _M_inner(std::move(__base)) +{ } + +constexpr auto +begin() +{ return _Iterator(*this, _M_inner.begin()); } + +constexpr auto +begin() const + requires range + && regular_invocable<__detail::__unarize, +range_reference_t> +{ return _Iterator(*this, _M_inner.begin()); } + +constexpr auto +end() +{ + if constexpr (common_range<_InnerView>) +return _Iterator(*this, _M_inner.end()); + else +return _Sentinel(_M_inner.end()); +} + +constexpr auto +end() const + requires range + && regular_invocable<__detail::__unarize, +range_reference_t> +{ + if constexpr (common_range) +return _Iterator(*this, _M_inner.end()); + else +return _Sentinel(_M_inner.end()); +} + +constexpr auto +size() requires sized_range<_InnerView> +{ return _M_inner.size(); } + +constexpr auto +size() const requires sized_range +{ return _M_inner.size(); } + }; + + template + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference, + range_reference_t<_Vp>>> + template + class adjacent_transform_view<_Vp, _Fp, _Nm>::_Iterator + { +using _Parent = __detail::__maybe_const_t<_Const, adjacent_transform_view>; +using _Base = __detail::__maybe_const_t<_Const, _Vp>; + +_Parent* _M_parent = nullptr; +_InnerIter<_Const> _M_inner; + +constexpr +_Iterator(_Parent& __parent,