diff --git a/stl/inc/ranges b/stl/inc/ranges index 776e1310efe..00a9e1faecd 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -987,14 +987,18 @@ namespace ranges { /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred; template - _NODISCARD constexpr auto operator()(_Rng&& _Range) const - noexcept(noexcept(filter_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)})) requires requires { - filter_view{static_cast<_Rng&&>(_Range), _STD move(*_Pred)}; + _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( + noexcept(filter_view{_STD forward<_Rng>(_Range), *_Pred})) requires requires { + filter_view{static_cast<_Rng&&>(_Range), *_Pred}; } - { - // clang-format on - return filter_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)}; + { return filter_view{_STD forward<_Rng>(_Range), *_Pred}; } + + template + _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept( + noexcept(filter_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)})) requires requires { + filter_view{static_cast<_Rng&&>(_Range), _STD move(*_Pred)}; } + { return filter_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)}; } }; public: @@ -1470,15 +1474,19 @@ namespace ranges { struct _Partial : _Pipe::_Base<_Partial<_Fn>> { /* [[no_unique_address]] */ _Semiregular_box<_Fn> _Fun; - // clang-format off template - _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(noexcept( - transform_view{_STD forward<_Rng>(_Range), _STD move(*_Fun)})) requires requires { + _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( + noexcept(transform_view{_STD forward<_Rng>(_Range), *_Fun})) requires requires { + transform_view{static_cast<_Rng&&>(_Range), *_Fun}; + } + { return transform_view{_STD forward<_Rng>(_Range), *_Fun}; } + + template + _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept( + noexcept(transform_view{_STD forward<_Rng>(_Range), _STD move(*_Fun)})) requires requires { transform_view{static_cast<_Rng&&>(_Range), _STD move(*_Fun)}; - } { - // clang-format on - return transform_view{_STD forward<_Rng>(_Range), _STD move(*_Fun)}; } + { return transform_view{_STD forward<_Rng>(_Range), _STD move(*_Fun)}; } }; public: diff --git a/tests/std/tests/P0896R4_views_filter/test.cpp b/tests/std/tests/P0896R4_views_filter/test.cpp index d28f5addcc3..8de9be5c052 100644 --- a/tests/std/tests/P0896R4_views_filter/test.cpp +++ b/tests/std/tests/P0896R4_views_filter/test.cpp @@ -380,4 +380,27 @@ int main() { STATIC_ASSERT((instantiation_test(), true)); instantiation_test(); + + { // Validate **non-standard guarantee** that predicates are moved into the range adaptor closure, and into the view + // object from an rvalue closure + struct Fn { + Fn() = default; + Fn(Fn&&) = default; + Fn(const Fn&) { + assert(false); + } + Fn& operator=(Fn&&) = default; + + Fn& operator=(const Fn&) { + assert(false); + return *this; + } + + bool operator()(int) const { + return true; + } + }; + + (void) views::filter(Fn{})(span{}); + } } diff --git a/tests/std/tests/P0896R4_views_transform/test.cpp b/tests/std/tests/P0896R4_views_transform/test.cpp index a683ba68583..8da8bd70448 100644 --- a/tests/std/tests/P0896R4_views_transform/test.cpp +++ b/tests/std/tests/P0896R4_views_transform/test.cpp @@ -710,4 +710,27 @@ int main() { STATIC_ASSERT((iterator_instantiation_test(), true)); iterator_instantiation_test(); + + { // Validate **non-standard guarantee** that predicates are moved into the range adaptor closure, and into the view + // object from an rvalue closure + struct Fn { + Fn() = default; + Fn(Fn&&) = default; + Fn(const Fn&) { + assert(false); + } + Fn& operator=(Fn&&) = default; + + Fn& operator=(const Fn&) { + assert(false); + return *this; + } + + bool operator()(int) const { + return true; + } + }; + + (void) views::transform(Fn{})(span{}); + } }