[libcxx-commits] [PATCH] D107098: [libc++] Implement the underlying mechanism for range adaptors

Christopher Di Bella via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Tue Aug 24 17:46:51 PDT 2021


cjdb added inline comments.


================
Comment at: libcxx/include/__ranges/range_adaptor.h:45-60
+template <ranges::viewable_range _View, class _Closure>
+    requires _RangeAdaptorClosure<decay_t<_Closure>>
+_LIBCPP_HIDE_FROM_ABI
+constexpr auto operator|(_View&& __view, _Closure&& __closure)
+noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Closure>(__closure), _VSTD::forward<_View>(__view))))
+-> decltype(      _VSTD::invoke(_VSTD::forward<_Closure>(__closure), _VSTD::forward<_View>(__view)))
+{ return          _VSTD::invoke(_VSTD::forward<_Closure>(__closure), _VSTD::forward<_View>(__view)); }
----------------
ldionne wrote:
> cjdb wrote:
> > cjdb wrote:
> > > cjdb wrote:
> > > > 
> > > I'd //really// like for us to make these hidden friends. It's definitely doable for `range | closure`, and I //think// it's doable for `closure | closure` too.
> > What am I saying? If it's possible for `range | closure`, of course it's possible for `closure | closure` :facepalm:
> This is what we'd end up with:
> 
> ```
> template <class _Closure>
> struct __range_adaptor_closure {
>     template <ranges::viewable_range _View>
>     _LIBCPP_HIDE_FROM_ABI
>     friend constexpr auto operator|(_View&& __view, _Closure&& __closure)
>     noexcept(noexcept(_VSTD::invoke(_VSTD::move(__closure), _VSTD::forward<_View>(__view))))
>     -> decltype(      _VSTD::invoke(_VSTD::move(__closure), _VSTD::forward<_View>(__view)))
>     { return          _VSTD::invoke(_VSTD::move(__closure), _VSTD::forward<_View>(__view)); }
> 
>     template <ranges::viewable_range _View>
>     _LIBCPP_HIDE_FROM_ABI
>     friend constexpr auto operator|(_View&& __view, _Closure const& __closure)
>     noexcept(noexcept(_VSTD::invoke(__closure, _VSTD::forward<_View>(__view))))
>     -> decltype(      _VSTD::invoke(__closure, _VSTD::forward<_View>(__view)))
>     { return          _VSTD::invoke(__closure, _VSTD::forward<_View>(__view)); }
> 
>     template <_RangeAdaptorClosure _OtherClosure>
>     _LIBCPP_HIDE_FROM_ABI
>     constexpr auto operator|(_Closure&& __c1, _OtherClosure&& __c2)
>     noexcept(noexcept(__range_adaptor_closure_t(_VSTD::__compose(_VSTD::forward<_OtherClosure>(__c2), _VSTD::move(__c1)))))
>     -> decltype(      __range_adaptor_closure_t(_VSTD::__compose(_VSTD::forward<_OtherClosure>(__c2), _VSTD::move(__c1))))
>     { return          __range_adaptor_closure_t(_VSTD::__compose(_VSTD::forward<_OtherClosure>(__c2), _VSTD::move(__c1))); }
> 
>     template <_RangeAdaptorClosure _OtherClosure>
>     _LIBCPP_HIDE_FROM_ABI
>     constexpr auto operator|(_Closure const& __c1, _OtherClosure&& __c2)
>     noexcept(noexcept(__range_adaptor_closure_t(_VSTD::__compose(_VSTD::forward<_OtherClosure>(__c2), __c1))))
>     -> decltype(      __range_adaptor_closure_t(_VSTD::__compose(_VSTD::forward<_OtherClosure>(__c2), __c1)))
>     { return          __range_adaptor_closure_t(_VSTD::__compose(_VSTD::forward<_OtherClosure>(__c2), __c1)); }
> };
> ```
> 
> A few remarks:
> 
> - For `range | closure`, it's not clear to me that we gain much since we need two overloads. And perhaps we'd actually need more to handle `_Closure&` and `_Closure const&&`?
> - For `closure | closure`, that simply doesn't work because that will cause an ambiguity. If we have two closures `Closure1 c1` and `Closure2 c2`, `c1 | c2` could use either the `operator|(Closure1, auto)` injected by `__range_adaptor_closure<Closure1>`, or the `operator|(Closure2, auto)` injected by `__range_adaptor_closure<Closure2>`. I don't see an easy way to solve that problem.
> 
> For those reasons, I'd be tempted to leave both as-is.
[[ https://godbolt.org/z/az96scex5 | Here's a minimised version ]] of what I have in mind. I don't think there's a lot you'll need to do to integrate it: just decorations and seeing if your existing concepts have a mapping (I couldn't see it: from what I could tell, we need both yours and mine).


================
Comment at: libcxx/include/__ranges/range_adaptor.h:45-49
+template <ranges::viewable_range _View, _RangeAdaptorClosure _Closure>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI
+constexpr auto operator|(_View&& __view, _Closure&& __closure)
+noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Closure>(__closure), _VSTD::forward<_View>(__view))))
+-> decltype(      _VSTD::invoke(_VSTD::forward<_Closure>(__closure), _VSTD::forward<_View>(__view)))
----------------
Unless I'm mistaken, the decltypes are only there for SFINAE friendliness?


================
Comment at: libcxx/include/__ranges/range_adaptor.h:56
+noexcept(noexcept(__range_adaptor_closure_t(_VSTD::__compose(_VSTD::forward<_Closure2>(__c2), _VSTD::forward<_Closure1>(__c1)))))
+-> decltype(      __range_adaptor_closure_t(_VSTD::__compose(_VSTD::forward<_Closure2>(__c2), _VSTD::forward<_Closure1>(__c1))))
+{ return          __range_adaptor_closure_t(_VSTD::__compose(_VSTD::forward<_Closure2>(__c2), _VSTD::forward<_Closure1>(__c1))); }
----------------
Ditto, but you'll also need a `constructible_from` for this one.


================
Comment at: libcxx/include/__ranges/transform_view.h:414
+    noexcept(noexcept(transform_view(_VSTD::forward<_Range>(__range), _VSTD::forward<_Fn>(__f))))
+    -> decltype(      transform_view(_VSTD::forward<_Range>(__range), _VSTD::forward<_Fn>(__f)))
+    { return          transform_view(_VSTD::forward<_Range>(__range), _VSTD::forward<_Fn>(__f)); }
----------------
Same dealeo as above: this should be a requirement, not expression-SFINAE. Gonna leave it at three comments, I trust you to find all the rest :-)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D107098/new/

https://reviews.llvm.org/D107098



More information about the libcxx-commits mailing list