Skip to content

Commit ec46d76

Browse files
fsb4000misccoAdamBuciorStephanTLavavej
authored
LWG-3520 iter_move and iter_swap are inconsistent for transform_view::iterator (#2200)
Co-authored-by: Michael Schellenberger Costa <mschellenbergercosta@googlemail.com> Co-authored-by: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
1 parent d4d409e commit ec46d76

File tree

4 files changed

+21
-42
lines changed

4 files changed

+21
-42
lines changed

stl/inc/ranges

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,15 +2038,6 @@ namespace ranges {
20382038
return *_It;
20392039
}
20402040
}
2041-
2042-
friend constexpr void iter_swap(const _Iterator& _Left, const _Iterator& _Right) _NOEXCEPT_IDL0(noexcept(
2043-
_RANGES iter_swap(_Left._Current, _Right._Current))) requires indirectly_swappable<iterator_t<_Base>> {
2044-
#if _ITERATOR_DEBUG_LEVEL != 0
2045-
_Left._Check_dereference();
2046-
_Right._Check_dereference();
2047-
#endif // _ITERATOR_DEBUG_LEVEL != 0
2048-
_RANGES iter_swap(_Left._Current, _Right._Current);
2049-
}
20502041
};
20512042

20522043
template <bool _Const>

tests/std/include/range_algorithm_support.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,3 +1449,8 @@ template <class R>
14491449
concept CanBool = requires(R&& r) {
14501450
std::forward<R>(r) ? true : false;
14511451
};
1452+
1453+
template <class I>
1454+
concept CanIterSwap = requires(I&& i1, I&& i2) {
1455+
ranges::iter_swap(std::forward<I>(i1), std::forward<I>(i2));
1456+
};

tests/std/tests/P0896R4_views_transform/test.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -509,16 +509,7 @@ struct iterator_instantiator {
509509
assert(ranges::iter_move(i0) == add8(mutable_ints[0])); // NB: moving from int leaves it unchanged
510510
STATIC_ASSERT(NOEXCEPT_IDL0(ranges::iter_move(i0)));
511511

512-
if constexpr (forward_iterator<Iter>) {
513-
auto i1 = ranges::next(i0);
514-
ranges::iter_swap(i0, i1);
515-
assert(mutable_ints[0] == 1);
516-
assert(mutable_ints[1] == 0);
517-
ranges::iter_swap(i1, i0);
518-
assert(mutable_ints[0] == 0);
519-
assert(mutable_ints[1] == 1);
520-
STATIC_ASSERT(NOEXCEPT_IDL0(ranges::iter_swap(i0, i1)));
521-
}
512+
STATIC_ASSERT(!CanIterSwap<decltype(i0)>);
522513
}
523514

524515
{ // Validate increments
@@ -784,4 +775,19 @@ int main() {
784775

785776
(void) views::transform(Fn{})(span<int>{});
786777
}
778+
779+
{ // Validate that iter_swap works when result of transformation is an lvalue reference
780+
char base[] = "hello";
781+
auto v = ranges::transform_view{base, [](char& c) -> char& { return c; }};
782+
auto i1 = v.begin();
783+
auto i2 = v.begin() + 1;
784+
785+
assert(*i1 == 'h');
786+
assert(*i2 == 'e');
787+
788+
ranges::iter_swap(i1, i2);
789+
790+
assert(*i1 == 'e');
791+
assert(*i2 == 'h');
792+
}
787793
}

tests/std/tests/P0896R4_views_transform_death/test.cpp

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -287,26 +287,6 @@ void test_iter_move_value_initialized_iterator() {
287287
(void) ranges::iter_move(i); // cannot dereference value-initialized transform_view iterator
288288
}
289289

290-
void test_iter_swap_value_initialized_iterators() {
291-
ranges::iterator_t<TV> i0{};
292-
ranges::iterator_t<TV> i1{};
293-
(void) ranges::iter_swap(i0, i1); // cannot dereference value-initialized transform_view iterator
294-
}
295-
296-
void test_iter_swap_value_initialized_iterator_left() {
297-
ranges::iterator_t<TV> i0{};
298-
TV r{some_ints, lambda};
299-
ranges::iterator_t<TV> i1 = r.begin();
300-
(void) ranges::iter_swap(i0, i1); // cannot dereference value-initialized transform_view iterator
301-
}
302-
303-
void test_iter_swap_value_initialized_iterator_right() {
304-
TV r{some_ints, lambda};
305-
ranges::iterator_t<TV> i0 = r.begin();
306-
ranges::iterator_t<TV> i1{};
307-
(void) ranges::iter_swap(i0, i1); // cannot dereference value-initialized transform_view iterator
308-
}
309-
310290
void test_sentinel_compare_value_initialized() {
311291
auto r = ranges::subrange{counted_iterator{some_ints, ranges::distance(some_ints)}, default_sentinel}
312292
| views::transform(lambda);
@@ -382,9 +362,6 @@ int main(int argc, char* argv[]) {
382362
test_operator_minus_incompatible_different,
383363
test_operator_minus_incompatible_value_initialized,
384364
test_iter_move_value_initialized_iterator,
385-
test_iter_swap_value_initialized_iterators,
386-
test_iter_swap_value_initialized_iterator_left,
387-
test_iter_swap_value_initialized_iterator_right,
388365
test_sentinel_compare_value_initialized,
389366
test_sentinel_difference_value_initialized,
390367
test_flipped_sentinel_difference_value_initialized,

0 commit comments

Comments
 (0)