[libcxx-commits] [PATCH] D101193: [libcxx][ranges] Add ranges::empty CPO.
Tim Song via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Apr 23 15:59:05 PDT 2021
tcanens added a subscriber: CaseyCarter.
tcanens added inline comments.
================
Comment at: libcxx/include/__ranges/empty.h:38
+ template<class _Tp>
+ concept __can_invoke_size = requires(_Tp&& __t) { ranges::size(__t); };
+
----------------
I'd expect this one and the next to require `!__member_empty`?
================
Comment at: libcxx/include/__ranges/empty.h:48
+
+ struct __fn {
+ template <__member_empty _Tp>
----------------
Quuxplusone wrote:
> Doesn't clearly implement a case corresponding to the bullet point ["If `T` is an array of unknown bound, `ranges::empty(E)` is ill-formed."](https://eel.is/c++draft/range.access#range.prim.empty-2.1)
> But I think that bullet point is actually redundant; arrays of unknown bound also don't have `ranges::end(E)` or `ranges::size(E)` or `t.begin()`.
> Do we understand the intent (in all these CPOs) when `T` is a //reference to// an array of unknown bound?
> Doesn't clearly implement a case corresponding to the bullet point ["If `T` is an array of unknown bound, `ranges::empty(E)` is ill-formed."](https://eel.is/c++draft/range.access#range.prim.empty-2.1)
> But I think that bullet point is actually redundant; arrays of unknown bound also don't have `ranges::end(E)` or `ranges::size(E)` or `t.begin()`.
The difference is that for array of unknown bound of incomplete type, `ranges::begin` / `ranges::end` are IFNDR, but `ranges::empty` is ill-formed DR.
> Do we understand the intent (in all these CPOs) when `T` is a //reference to// an array of unknown bound?
`T` is the type of some expression. Expressions don't have reference type.
================
Comment at: libcxx/include/__ranges/empty.h:50-53
+ [[nodiscard]] constexpr bool operator()(_Tp&& __t) const
+ noexcept(noexcept(_VSTD::forward<_Tp>(__t).empty())) {
+ return _VSTD::forward<_Tp>(__t).empty();
+ }
----------------
zoecarver wrote:
> cjdb wrote:
> > Quuxplusone wrote:
> > > As usual, replace `X` with `bool(X)` in the noexcept-spec and also in the return. Also, `__t` should be an lvalue according to "let t be an lvalue that denotes the reified object for E." So:
> > > ```
> > > [[nodiscard]] constexpr bool operator()(_Tp&& __t) const
> > > noexcept(noexcept(bool(__t.empty()))) {
> > > return __t.empty();
> > > }
> > > ```
> > > Optionally, figure out a way to detect the difference here and write a regression test for it. (I say "optionally" because IMHO it doesn't really matter.)
> > >
> > > As above so on lines 34 and 57/58: `t` is an lvalue, lose the forwarding.
> > > and also in the return
> >
> > This shouldn't be necessary thanks to //`boolean-testable`//. @tcanens I don't think the wording permit us to use it right now; did we miss one in the cleanup?
> Good catch, thanks. I'm not going to do `bool(X)` for the overload on L57 because we know that it's a primitive type.
> > and also in the return
>
> This shouldn't be necessary thanks to //`boolean-testable`//. @tcanens I don't think the wording permit us to use it right now; did we miss one in the cleanup?
This one doesn't even require the result to be implicitly convertible to `bool`, which is probably why I didn't touch it with //`boolean-testable`//. I don't know what the original intended design is - @CaseyCarter?
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D101193/new/
https://reviews.llvm.org/D101193
More information about the libcxx-commits
mailing list