From 898428aa479db688d74cd6538502bb2f416ea75b Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 5 Jul 2024 02:29:28 +0800 Subject: [PATCH 1/4] Implement LWG-4083 --- stl/inc/ranges | 2 +- tests/std/tests/P2446R2_views_as_rvalue/test.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 8129f9b14c6..6f7e4d06d97 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -1532,7 +1532,7 @@ namespace ranges { template _NODISCARD static consteval _Choice_t<_St> _Choose() noexcept { - if constexpr (same_as, range_reference_t<_Rng>>) { + if constexpr (input_range<_Rng> && same_as, range_reference_t<_Rng>>) { return {_St::_All, noexcept(views::all(_STD declval<_Rng>()))}; } else if constexpr (_Can_as_rvalue<_Rng>) { return {_St::_As_rvalue, noexcept(as_rvalue_view{_STD declval<_Rng>()})}; diff --git a/tests/std/tests/P2446R2_views_as_rvalue/test.cpp b/tests/std/tests/P2446R2_views_as_rvalue/test.cpp index 0a68c5d8901..3668e8341d7 100644 --- a/tests/std/tests/P2446R2_views_as_rvalue/test.cpp +++ b/tests/std/tests/P2446R2_views_as_rvalue/test.cpp @@ -401,6 +401,17 @@ void test_example_from_p2446r2() { assert(ranges::all_of(words, ranges::empty)); // all strings from words are empty (implementation assumption) } +// LWG-4083 "views::as_rvalue should reject non-input ranges" +struct OutputRvalueIterator { + using difference_type = int; + int operator*() const; + OutputRvalueIterator& operator++(); + void operator++(int); +}; +using OutputRvalueRange = decltype(ranges::subrange{OutputRvalueIterator{}, unreachable_sentinel}); + +static_assert(!CanViewAsRvalue); + int main() { { // Validate views // ... copyable From e89a1ff9fc0d5c889fe0724285a2a6f01ddc7611 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sat, 6 Jul 2024 18:54:09 +0800 Subject: [PATCH 2/4] Workaround for DevCom-10698021 --- stl/inc/ranges | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stl/inc/ranges b/stl/inc/ranges index 6f7e4d06d97..174bfde85af 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -1524,7 +1524,11 @@ namespace ranges { namespace views { template +#ifdef __EDG__ // TRANSITION, DevCom-10698021 + concept _Can_as_rvalue = requires(_Rng&& __r) { as_rvalue_view(static_cast<_Rng&&>(__r)); }; +#else // ^^^ workaround / no workaround vvv concept _Can_as_rvalue = requires(_Rng&& __r) { as_rvalue_view{static_cast<_Rng&&>(__r)}; }; +#endif // ^^^ no workaround ^^^ class _As_rvalue_fn : public _Pipe::_Base<_As_rvalue_fn> { private: From 5450af73b733bb2860501e40c021dada0b544d8d Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sun, 7 Jul 2024 22:11:31 +0800 Subject: [PATCH 3/4] "perma-workaround" the direct-initialization --- stl/inc/ranges | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 61c5ee94eea..9774f82bc17 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -1523,12 +1523,10 @@ namespace ranges { constexpr auto _Compile_time_max_size> = _Compile_time_max_size; namespace views { + // direct-intialization is specified in the Standard (N4981 [range.as.rvalue.overview]/2.2) + // and needed for EDG, DevCom-10698021 template -#ifdef __EDG__ // TRANSITION, DevCom-10698021 concept _Can_as_rvalue = requires(_Rng&& __r) { as_rvalue_view(static_cast<_Rng&&>(__r)); }; -#else // ^^^ workaround / no workaround vvv - concept _Can_as_rvalue = requires(_Rng&& __r) { as_rvalue_view{static_cast<_Rng&&>(__r)}; }; -#endif // ^^^ no workaround ^^^ class _As_rvalue_fn : public _Pipe::_Base<_As_rvalue_fn> { private: From 7a6660671dbb3a7f318381e4d4598463701ee83a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 8 Jul 2024 06:37:39 -0700 Subject: [PATCH 4/4] Code review feedback. --- stl/inc/ranges | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 9774f82bc17..3f8faa137e1 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -1523,7 +1523,7 @@ namespace ranges { constexpr auto _Compile_time_max_size> = _Compile_time_max_size; namespace views { - // direct-intialization is specified in the Standard (N4981 [range.as.rvalue.overview]/2.2) + // direct-non-list-initialization is specified in the Standard (N4981 [range.as.rvalue.overview]/2.2) // and needed for EDG, DevCom-10698021 template concept _Can_as_rvalue = requires(_Rng&& __r) { as_rvalue_view(static_cast<_Rng&&>(__r)); }; @@ -1537,7 +1537,7 @@ namespace ranges { if constexpr (input_range<_Rng> && same_as, range_reference_t<_Rng>>) { return {_St::_All, noexcept(views::all(_STD declval<_Rng>()))}; } else if constexpr (_Can_as_rvalue<_Rng>) { - return {_St::_As_rvalue, noexcept(as_rvalue_view{_STD declval<_Rng>()})}; + return {_St::_As_rvalue, noexcept(as_rvalue_view(_STD declval<_Rng>()))}; } else { return {_St::_None}; } @@ -1555,7 +1555,7 @@ namespace ranges { if constexpr (_Strat == _St::_All) { return views::all(_STD forward<_Rng>(_Range)); } else if constexpr (_Strat == _St::_As_rvalue) { - return as_rvalue_view{_STD forward<_Rng>(_Range)}; + return as_rvalue_view(_STD forward<_Rng>(_Range)); } else { _STL_INTERNAL_STATIC_ASSERT(false); // unexpected strategy }