[libcxx-commits] [PATCH] D128281: [libc++] fix views::all hard error on lvalue move only views instead of SFINAE
Hui via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jun 21 11:55:40 PDT 2022
huixie90 marked 3 inline comments as done.
huixie90 added inline comments.
================
Comment at: libcxx/include/__ranges/all.h:42
noexcept(noexcept(_LIBCPP_AUTO_CAST(std::forward<_Tp>(__t))))
+ -> decltype(_LIBCPP_AUTO_CAST(std::forward<_Tp>(__t)))
{
----------------
EricWF wrote:
> var-const wrote:
> > I wonder if we have any other cases where we don't write the return type 3 times and consequently don't get SFINAE.
> Is this a case of "not getting SFINAE" or "auto" return types not deducing to reference types? Does this work if we use `decltype(auto)` instead?
>
> Also this changes the return type from being by-value to being by-reference, which is the intended change I assume?
This function always return by value because `_LIBCPP_AUTO_CAST` always yield the decayed type
```
#define _LIBCPP_AUTO_CAST(expr) static_cast<typename decay<decltype((expr))>::type>(expr)
```
In the spec, it says expression equivalent to `decay-copy(E)`, and `_LIBCPP_AUTO_CAST` is the libc++ way of implementing `decay-copy`
In any case, the return type should be the same as `decay-copy` (expression equivalent), and this is why `decltype(_LIBCPP_AUTO_CAST(...))` is correct
`decltype(auto)` won't work because `decltype(auto)` doesn't have any effect on SFINAE
================
Comment at: libcxx/test/std/ranges/range.adaptors/range.all/all.pass.cpp:153
static_assert(!std::is_invocable_v<decltype(std::views::all), RandomAccessRange, RandomAccessRange>);
+ static_assert(!std::is_invocable_v<decltype(std::views::all), MoveOnlyView&>);
}
----------------
jloser wrote:
> var-const wrote:
> > Is it important for the view to be move-only? From the patch description, I got the impression that any reference should fail, but perhaps I'm missing something?
> The call operator already requires the template type be a view, so an lvalue reference to a view is the simplest case to make it go boom AFAICT.
"move-only" is important here because `_LIBCPP_AUTO_CAST` (which is used in the all's function body, and noexcept specification) is going to make a copy.
see definition here
```
#define _LIBCPP_AUTO_CAST(expr) static_cast<typename decay<decltype((expr))>::type>(expr)
```
If we pass an lvalue reference to a copyable `view`, the expression above is just making a copy of the `view`, which is fine. If the `view` is move-only, the above expression is ill-formed and cause `noexcept(decay-copy(v))` go boom
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D128281/new/
https://reviews.llvm.org/D128281
More information about the libcxx-commits
mailing list