From 7ebae725180546f6356a062937df20965ea625f4 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 2 Jan 2023 00:42:48 +0800 Subject: [PATCH 1/5] Test coverage for LWG-3737 --- tests/std/tests/P0896R4_views_take/test.cpp | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/std/tests/P0896R4_views_take/test.cpp b/tests/std/tests/P0896R4_views_take/test.cpp index abb90762afd..0d9d22ca743 100644 --- a/tests/std/tests/P0896R4_views_take/test.cpp +++ b/tests/std/tests/P0896R4_views_take/test.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include @@ -506,6 +508,36 @@ void test_DevCom_1397309() { assert(ranges::equal(values | ranges::views::take(2) | ranges::views::keys, expected)); } +struct read_some_int_range : ranges::subrange>, default_sentinel_t> { + using ranges::subrange>, default_sentinel_t>::subrange; +}; + +template <> +inline constexpr bool ranges::disable_sized_range = true; + +void test_lwg3737() { + static_assert(ranges::input_range); + static_assert(ranges::input_range); + static_assert(!ranges::sized_range); + static_assert(!ranges::sized_range); + + istringstream stream{"0 1 42 1729"}; + auto rng = + read_some_int_range{counted_iterator{istream_iterator{stream}, 4}, default_sentinel} | views::take(2); + + using result_range = decltype(rng); + static_assert( + is_same_v, counted_iterator>>>); + static_assert(is_same_v, default_sentinel_t>); + + static_assert( + is_same_v, counted_iterator>>>); + static_assert(is_same_v, default_sentinel_t>); + + vector vec{from_range, rng}; + assert(ranges::size(vec) == 2); + assert((vec == vector{0, 1})); +} int main() { // Validate views @@ -576,4 +608,6 @@ int main() { } test_DevCom_1397309(); + + test_lwg3737(); } From 3bd28629bef947b0e111d10b6a1c516017999e2e Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 2 Jan 2023 00:47:35 +0800 Subject: [PATCH 2/5] Implement LWG-3737 --- stl/inc/ranges | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/stl/inc/ranges b/stl/inc/ranges index ef960d5722f..52e23b79d2a 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -2624,6 +2624,10 @@ namespace ranges { const auto _Size = static_cast>(size()); return counted_iterator(_RANGES begin(_Range), _Size); } + } else if constexpr (sized_sentinel_for, iterator_t<_Vw>>) { + auto _Iter = _RANGES begin(_Range); + const auto _Size = _STD min(_Count, _RANGES end(_Range) - _Iter); + return counted_iterator(_STD move(_Iter), _Size); } else { return counted_iterator(_RANGES begin(_Range), _Count); } @@ -2639,6 +2643,10 @@ namespace ranges { const auto _Size = static_cast>(size()); return counted_iterator(_RANGES begin(_Range), _Size); } + } else if constexpr (sized_sentinel_for, iterator_t>) { + auto _Iter = _RANGES begin(_Range); + const auto _Size = _STD min(_Count, _RANGES end(_Range) - _Iter); + return counted_iterator(_STD move(_Iter), _Size); } else { return counted_iterator(_RANGES begin(_Range), _Count); } @@ -2653,6 +2661,8 @@ namespace ranges { } else { return default_sentinel; } + } else if constexpr (sized_sentinel_for, iterator_t<_Vw>>) { + return default_sentinel; } else { return _Sentinel{_RANGES end(_Range)}; } @@ -2667,6 +2677,8 @@ namespace ranges { } else { return default_sentinel; } + } else if constexpr (sized_sentinel_for, iterator_t>) { + return default_sentinel; } else { return _Sentinel{_RANGES end(_Range)}; } From e97418672362348d72dcdc168ce05ca137730885 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 2 Jan 2023 01:14:01 +0800 Subject: [PATCH 3/5] Avoid using C++23 `from_range` constructor --- tests/std/tests/P0896R4_views_take/test.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/std/tests/P0896R4_views_take/test.cpp b/tests/std/tests/P0896R4_views_take/test.cpp index 0d9d22ca743..23d0f0075c1 100644 --- a/tests/std/tests/P0896R4_views_take/test.cpp +++ b/tests/std/tests/P0896R4_views_take/test.cpp @@ -534,7 +534,11 @@ void test_lwg3737() { is_same_v, counted_iterator>>>); static_assert(is_same_v, default_sentinel_t>); - vector vec{from_range, rng}; + vector vec{}; + for (const int elem : rng) { + vec.push_back(elem); + } + assert(ranges::size(vec) == 2); assert((vec == vector{0, 1})); } From 99ddd3fd750406d464e60f4fe894d5b3799ee8b1 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 3 Jan 2023 07:19:06 +0800 Subject: [PATCH 4/5] Style improvement due to @CaseyCarter's review comments --- tests/std/tests/P0896R4_views_take/test.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P0896R4_views_take/test.cpp b/tests/std/tests/P0896R4_views_take/test.cpp index 23d0f0075c1..3a868a43384 100644 --- a/tests/std/tests/P0896R4_views_take/test.cpp +++ b/tests/std/tests/P0896R4_views_take/test.cpp @@ -508,6 +508,7 @@ void test_DevCom_1397309() { assert(ranges::equal(values | ranges::views::take(2) | ranges::views::keys, expected)); } + struct read_some_int_range : ranges::subrange>, default_sentinel_t> { using ranges::subrange>, default_sentinel_t>::subrange; }; @@ -535,9 +536,7 @@ void test_lwg3737() { static_assert(is_same_v, default_sentinel_t>); vector vec{}; - for (const int elem : rng) { - vec.push_back(elem); - } + ranges::copy(rng, back_inserter(vec)); assert(ranges::size(vec) == 2); assert((vec == vector{0, 1})); From f09b217e9491fd458a3cbdda1db7d8be45cd4b2a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 9 Jan 2023 16:47:31 -0800 Subject: [PATCH 5/5] Defend against macroization. --- stl/inc/ranges | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 52e23b79d2a..30531180aa6 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -2626,7 +2626,7 @@ namespace ranges { } } else if constexpr (sized_sentinel_for, iterator_t<_Vw>>) { auto _Iter = _RANGES begin(_Range); - const auto _Size = _STD min(_Count, _RANGES end(_Range) - _Iter); + const auto _Size = (_STD min)(_Count, _RANGES end(_Range) - _Iter); return counted_iterator(_STD move(_Iter), _Size); } else { return counted_iterator(_RANGES begin(_Range), _Count); @@ -2645,7 +2645,7 @@ namespace ranges { } } else if constexpr (sized_sentinel_for, iterator_t>) { auto _Iter = _RANGES begin(_Range); - const auto _Size = _STD min(_Count, _RANGES end(_Range) - _Iter); + const auto _Size = (_STD min)(_Count, _RANGES end(_Range) - _Iter); return counted_iterator(_STD move(_Iter), _Size); } else { return counted_iterator(_RANGES begin(_Range), _Count);