Skip to content

Commit 994f941

Browse files
LWG-3851: chunk_view::inner-iterator missing custom iter_move and iter_swap (#3517)
Co-authored-by: Stephan T. Lavavej <[email protected]>
1 parent 649128c commit 994f941

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

stl/inc/ranges

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6377,6 +6377,10 @@ namespace ranges {
63776377
return (_STD min)(_Parent->_Remainder, _RANGES end(_Parent->_Range) - *_Parent->_Current);
63786378
}
63796379

6380+
_NODISCARD constexpr const iterator_t<_Vw>& _Get_current() const noexcept {
6381+
return *_Parent->_Current;
6382+
}
6383+
63806384
public:
63816385
using iterator_concept = input_iterator_tag;
63826386
using difference_type = range_difference_t<_Vw>;
@@ -6443,6 +6447,18 @@ namespace ranges {
64436447
{
64446448
return -_Left._Get_size();
64456449
}
6450+
6451+
_NODISCARD_FRIEND constexpr range_rvalue_reference_t<_Vw> iter_move(const _Inner_iterator& _It) noexcept(
6452+
noexcept(_RANGES iter_move(_It._Get_current()))) {
6453+
return _RANGES iter_move(_It._Get_current());
6454+
}
6455+
6456+
friend constexpr void iter_swap(const _Inner_iterator& _Left, const _Inner_iterator& _Right) noexcept(
6457+
noexcept(_RANGES iter_swap(_Left._Get_current(), _Right._Get_current())))
6458+
requires indirectly_swappable<iterator_t<_Vw>>
6459+
{
6460+
_RANGES iter_swap(_Left._Get_current(), _Right._Get_current());
6461+
}
64466462
};
64476463

64486464
class _Outer_iterator {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Copyright (c) Microsoft Corporation.
22
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
33

4-
RUNALL_INCLUDE ..\concepts_latest_matrix.lst
4+
RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst

tests/std/tests/P2442R1_views_chunk/test.cpp

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <forward_list>
77
#include <ranges>
88
#include <span>
9+
#include <sstream>
10+
#include <string>
911
#include <type_traits>
1012
#include <utility>
1113
#include <vector>
@@ -464,8 +466,9 @@ template <ranges::input_range Rng, class Expected>
464466
constexpr bool test_input(Rng&& rng, Expected&& expected) {
465467
using ranges::chunk_view, ranges::equal, ranges::iterator_t, ranges::sentinel_t;
466468

467-
using V = views::all_t<Rng>;
468-
using R = chunk_view<V>;
469+
using V = views::all_t<Rng>;
470+
using BI = iterator_t<V>;
471+
using R = chunk_view<V>;
469472

470473
same_as<R> auto r = chunk_view{forward<Rng>(rng), 2};
471474
auto outer_iter = r.begin();
@@ -478,6 +481,19 @@ constexpr bool test_input(Rng&& rng, Expected&& expected) {
478481

479482
auto inner_iter = val_ty.begin();
480483
same_as<default_sentinel_t> auto inner_sen = val_ty.end();
484+
485+
{ // Check iter_move (other tests are defined in 'test_lwg3851' function)
486+
same_as<ranges::range_rvalue_reference_t<Rng>> decltype(auto) rval = iter_move(as_const(inner_iter));
487+
assert(rval == expected[0][0]);
488+
STATIC_ASSERT(noexcept(iter_move(inner_iter)) == noexcept(ranges::iter_move(declval<const BI&>())));
489+
}
490+
491+
if constexpr (indirectly_swappable<BI>) { // Check iter_swap (other tests are defined in 'test_lwg3851' function)
492+
STATIC_ASSERT(is_void_v<decltype(iter_swap(as_const(inner_iter), as_const(inner_iter)))>);
493+
STATIC_ASSERT(noexcept(iter_swap(inner_iter, inner_iter))
494+
== noexcept(ranges::iter_swap(declval<const BI&>(), declval<const BI&>())));
495+
}
496+
481497
assert(inner_iter != inner_sen);
482498
if constexpr (sized_sentinel_for<sentinel_t<Rng>, iterator_t<Rng>>) {
483499
assert(inner_sen - inner_iter == 2);
@@ -579,6 +595,38 @@ using move_only_view = test::range<Category, const int, test::Sized{is_random},
579595
IsCommon, test::CanCompare{derived_from<Category, forward_iterator_tag>},
580596
test::ProxyRef{!derived_from<Category, contiguous_iterator_tag>}, test::CanView::yes, test::Copyability::move_only>;
581597

598+
// Check LWG-3851: 'chunk_view::inner-iterator missing custom iter_move and iter_swap'
599+
void test_lwg3851() {
600+
{ // Check 'iter_move'
601+
istringstream ints{"0 1 2 3 4"};
602+
auto v = views::istream<int>(ints) | views::chunk(2);
603+
auto o = v.begin();
604+
auto c = *o;
605+
auto i = c.begin();
606+
607+
same_as<int&&> decltype(auto) rval = iter_move(i);
608+
assert(rval == 0);
609+
}
610+
611+
{ // Check 'iter_swap'
612+
istringstream ints1{"0 1 2 3 4"};
613+
auto v1 = views::istream<int>(ints1) | views::chunk(2);
614+
auto o1 = v1.begin();
615+
auto c1 = *o1;
616+
auto i1 = c1.begin();
617+
618+
istringstream ints2{"5 6 7 8 9"};
619+
auto v2 = views::istream<int>(ints2) | views::chunk(2);
620+
auto o2 = v2.begin();
621+
auto c2 = *o2;
622+
auto i2 = c2.begin();
623+
624+
iter_swap(as_const(i1), as_const(i2));
625+
assert(*i1 == 5);
626+
assert(*i2 == 0);
627+
}
628+
}
629+
582630
int main() {
583631
{ // Validate views
584632
// ... copyable
@@ -617,4 +665,6 @@ int main() {
617665

618666
STATIC_ASSERT((instantiation_test(), true));
619667
instantiation_test();
668+
669+
test_lwg3851();
620670
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Copyright (c) Microsoft Corporation.
22
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
33

4-
RUNALL_INCLUDE ..\concepts_latest_matrix.lst
4+
RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst

0 commit comments

Comments
 (0)