[gcc(refs/users/ppalka/heads/libstdcxx-constrained-algos)] Make ranges::copy and ranges::move unmoveable-iterator-safe
Patrick Palka
ppalka@gcc.gnu.org
Wed Jan 22 22:34:00 GMT 2020
https://gcc.gnu.org/g:9800597b81fc95c3dbe3e46a2657d4bd0fb59921
commit 9800597b81fc95c3dbe3e46a2657d4bd0fb59921
Author: Patrick Palka <ppalka@redhat.com>
Date: Wed Jan 22 17:07:31 2020 -0500
Make ranges::copy and ranges::move unmoveable-iterator-safe
Diff:
---
libstdc++-v3/include/bits/ranges_algo.h | 54 +++++++++++-----------
.../testsuite/25_algorithms/copy/constrained.cc | 21 +++++----
.../testsuite/25_algorithms/move/constrained.cc | 21 +++++----
3 files changed, 49 insertions(+), 47 deletions(-)
diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index 6788085..8ea616b 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -816,16 +816,14 @@ namespace ranges
template<typename _Iter, typename _Out>
using move_result = copy_result<_Iter, _Out>;
- template<bool _IsMove,
- input_iterator _Iter, sentinel_for<_Iter> _Sent,
- weakly_incrementable _Out>
+ template<bool _IsMove, typename _Iter, typename _Sent, typename _Out>
requires (_IsMove
- ? indirectly_movable<_Iter, _Out>
- : indirectly_copyable<_Iter, _Out>)
+ ? indirectly_movable<remove_reference_t<_Iter>, _Out>
+ : indirectly_copyable<remove_reference_t<_Iter>, _Out>)
constexpr conditional_t<_IsMove,
- move_result<_Iter, _Out>,
- copy_result<_Iter, _Out>>
- __copy_or_move(_Iter __first, _Sent __last, _Out __result)
+ move_result<remove_reference_t<_Iter>, _Out>,
+ copy_result<remove_reference_t<_Iter>, _Out>>
+ __copy_or_move(_Iter&& __first, _Sent __last, _Out __result)
{
// TODO: implement more specializations to be at least on par with
// std::copy/std::move.
@@ -860,7 +858,7 @@ namespace ranges
__first++;
__result++;
}
- return {__first, __result};
+ return {std::move(__first), std::move(__result)};
}
}
else
@@ -874,7 +872,7 @@ namespace ranges
__first++;
__result++;
}
- return {__first, __result};
+ return {std::move(__first), std::move(__result)};
}
}
@@ -887,24 +885,24 @@ namespace ranges
constexpr bool __move_iterator_p = __is_move_iterator<_Iter>::__value;
if constexpr (__move_iterator_p)
{
- auto __first_base = __first.base();
- auto __last_base = __last.base();
+ auto __first_base = std::move(__first).base();
+ auto __last_base = std::move(__last).base();
auto [__in,__out]
- = ranges::__copy_or_move<true>(std::__niter_base(__first_base),
- std::__niter_base(__last_base),
- std::__niter_base(__result));
- auto __wrapped_in = std::__niter_wrap(__first_base, __in);
- auto __wrapped_out = std::__niter_wrap(__result, __out);
- return {move_iterator{__wrapped_in}, __wrapped_out};
+ = ranges::__copy_or_move<true>(std::__niter_base(std::move(__first_base)),
+ std::__niter_base(std::move(__last_base)),
+ std::__niter_base(std::move(__result)));
+ auto __wrapped_in = std::__niter_wrap(__first_base, std::move(__in));
+ auto __wrapped_out = std::__niter_wrap(__result, std::move(__out));
+ return {move_iterator{std::move(__wrapped_in)}, std::move(__wrapped_out)};
}
else
{
auto [__in,__out]
- = ranges::__copy_or_move<false>(std::__niter_base(__first),
- std::__niter_base(__last),
- std::__niter_base(__result));
- return {std::__niter_wrap(__first, __in),
- std::__niter_wrap(__result, __out)};
+ = ranges::__copy_or_move<false>(std::__niter_base(std::move(__first)),
+ std::__niter_base(std::move(__last)),
+ std::__niter_base(std::move(__result)));
+ return {std::__niter_wrap(std::move(__first), std::move(__in)),
+ std::__niter_wrap(std::move(__result), std::move(__out))};
}
}
@@ -924,13 +922,15 @@ namespace ranges
move(_Iter __first, _Sent __last, _Out __result)
{
if constexpr (__is_move_iterator<_Iter>::__value)
- return ranges::copy(__first, __last, __result);
+ return ranges::copy(std::move(__first), std::move(__last),
+ std::move(__result));
else
{
auto [__in, __out]
- = ranges::copy(move_iterator<_Iter>{__first},
- move_sentinel<_Sent>{__last}, __result);
- return {__in.base(), __out};
+ = ranges::copy(move_iterator<_Iter>{std::move(__first)},
+ move_sentinel<_Sent>{std::move(__last)},
+ std::move(__result));
+ return {std::move(__in).base(), std::move(__out)};
}
}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc
index f1b94ff..f6cddc5 100644
--- a/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc
@@ -25,8 +25,8 @@
using __gnu_test::test_container;
using __gnu_test::test_range;
using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
using __gnu_test::forward_iterator_wrapper;
-using __gnu_test::bidirectional_iterator_wrapper;
namespace ranges = std::ranges;
@@ -48,8 +48,8 @@ test01()
int z[3] = { 1, 2, 3 };
test_container<int, forward_iterator_wrapper> cx(x);
test_container<char, forward_iterator_wrapper> cy(y);
- auto [in, out] = ranges::copy(x, y);
- VERIFY( ranges::equal(x, x+3, y, y+3) && in == x+3 && out == y+3 );
+ auto [in, out] = ranges::copy(cx, ranges::begin(cy));
+ VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 );
VERIFY( ranges::equal(x, z) );
}
@@ -57,10 +57,10 @@ test01()
char x[3] = { 1, 2, 3 };
int y[4] = { 0 };
int z[3] = { 1, 2, 3 };
- test_range<char, forward_iterator_wrapper> cx(x);
- test_range<int, forward_iterator_wrapper> cy(y);
- auto [in, out] = ranges::copy(x, y);
- VERIFY( ranges::equal(x, x+3, y, y+3) && in == x+3 && out == y+3 );
+ test_range<char, input_iterator_wrapper> rx(x);
+ test_range<int, output_iterator_wrapper> ry(y);
+ auto [in, out] = ranges::copy(rx, ranges::begin(ry));
+ VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 );
VERIFY( ranges::equal(x, z) );
}
}
@@ -135,10 +135,11 @@ test04()
Y x[7] = { 1, 2, 3, 4, 5, 6, 7 };
Y y[7] = { 0, 0, 0, 0, 0, 0, 0 };
Y z[7] = { 1, 2, 3, 4, 5, 6, 7 };
- auto [in, out] = ranges::copy(std::move_iterator{ranges::begin(x)},
- std::move_sentinel{ranges::end(x)},
+ test_range<Y, input_iterator_wrapper> rx(x);
+ auto [in, out] = ranges::copy(std::move_iterator{ranges::begin(rx)},
+ std::move_sentinel{ranges::end(rx)},
ranges::begin(y));
- VERIFY( ranges::equal(x, y) && in.base() == x+7 && out == y+7 );
+ VERIFY( ranges::equal(x, y) && std::move(in).base().ptr == x+7 && out == y+7 );
VERIFY( ranges::equal(x, z) );
for (const auto& v : x)
VERIFY( v.moved == 1 );
diff --git a/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc
index 7ec1e78..ab4d283 100644
--- a/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc
@@ -25,8 +25,8 @@
using __gnu_test::test_container;
using __gnu_test::test_range;
using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
using __gnu_test::forward_iterator_wrapper;
-using __gnu_test::bidirectional_iterator_wrapper;
namespace ranges = std::ranges;
@@ -76,8 +76,8 @@ test01()
int z[3] = { 1, 2, 3 };
test_container<int, forward_iterator_wrapper> cx(x);
test_container<char, forward_iterator_wrapper> cy(y);
- auto [in, out] = ranges::move(x, y);
- VERIFY( ranges::equal(x, x+3, y, y+3) && in == x+3 && out == y+3 );
+ auto [in, out] = ranges::move(cx, cy.begin());
+ VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 );
VERIFY( ranges::equal(x, z) );
}
@@ -85,10 +85,10 @@ test01()
char x[3] = { 1, 2, 3 };
int y[4] = { 0 };
int z[3] = { 1, 2, 3 };
- test_range<char, forward_iterator_wrapper> cx(x);
- test_range<int, forward_iterator_wrapper> cy(y);
- auto [in, out] = ranges::move(x, y);
- VERIFY( ranges::equal(x, x+3, y, y+3) && in == x+3 && out == y+3 );
+ test_range<char, input_iterator_wrapper> cx(x);
+ test_range<int, output_iterator_wrapper> cy(y);
+ auto [in, out] = ranges::move(cx, ranges::begin(cy));
+ VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 );
VERIFY( ranges::equal(x, z) );
}
}
@@ -133,11 +133,12 @@ test04()
X x[] = { {2}, {2}, {6}, {8}, {10} };
X y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
X z[] = { {2}, {2}, {6}, {8}, {10} };
- auto [in, out] = ranges::move(std::move_iterator{ranges::begin(x)},
- std::move_iterator{ranges::end(x)},
+ test_range<X, input_iterator_wrapper> rx(x);
+ auto [in, out] = ranges::move(std::move_iterator{ranges::begin(rx)},
+ std::move_sentinel{ranges::end(rx)},
ranges::begin(y));
VERIFY( ranges::equal(x, x+5, y, y+5) );
- VERIFY( in.base() == x+5 );
+ VERIFY( std::move(in).base().ptr == x+5 );
VERIFY( out == y+5 );
VERIFY( y[5].i == 2 );
VERIFY( ranges::equal(x, z) );
More information about the Libstdc++-cvs
mailing list