[gcc(refs/users/ppalka/heads/libstdcxx-constrained-algos)] sentinel/iterator confusion fixes
Patrick Palka
ppalka@gcc.gnu.org
Tue Jan 21 22:41:00 GMT 2020
https://gcc.gnu.org/g:ea1210e645b64888cac63227a444684664a1d45c
commit ea1210e645b64888cac63227a444684664a1d45c
Author: Patrick Palka <ppalka@gcc.gnu.org>
Date: Tue Jan 21 15:46:52 2020 -0500
sentinel/iterator confusion fixes
A sentinel is generally not convertible to an iterator, so avoid using a
sentinel where an iterator is expected. Included are some extra tests that
exercise this distinction.
Diff:
---
libstdc++-v3/include/bits/ranges_algo.h | 68 +++++++++++-----------
.../25_algorithms/find_end/constrained.cc | 10 ++++
.../25_algorithms/remove_if/constrained.cc | 2 +-
.../25_algorithms/search_n/constrained.cc | 3 +
4 files changed, 49 insertions(+), 34 deletions(-)
diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index cf3d7fc..291d0ac 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -138,7 +138,7 @@ namespace ranges
{
for (; __first != __last; ++__first)
std::__invoke(__f, std::__invoke(__proj, *__first));
- return { __last, std::move(__f) };
+ return { __first, std::move(__f) };
}
template<input_range _Range, typename _Proj = identity,
@@ -235,7 +235,7 @@ namespace ranges
std::__invoke(__proj1, *__first1),
std::__invoke(__proj2, *__iter)))
return __first1;
- return __last1;
+ return __first1;
}
template<input_range _Range1, forward_range _Range2,
@@ -377,7 +377,7 @@ namespace ranges
for (;;)
{
if (__first1 == __last1)
- return {__last1, __last1};
+ return {__first1, __first1};
if (std::__invoke(__pred,
std::__invoke(__proj1, *__first1),
std::__invoke(__proj2, *__first2)))
@@ -391,7 +391,7 @@ namespace ranges
if (++__cur2 == __last2)
return {__first1, ++__cur1};
if (++__cur1 == __last1)
- return {__last1, __last1};
+ return {__cur1, __cur1};
if (!std::__invoke(__pred,
std::__invoke(__proj1, *__cur1),
std::__invoke(__proj2, *__cur2)))
@@ -436,12 +436,11 @@ namespace ranges
__first = ranges::find_if(std::move(__first), __last,
std::move(__value_comp), std::move(__proj));
if (__first == __last)
- return {__last, __last};
+ return {__first, __first};
else
{
- __last = __first;
- ++__last;
- return {__first, __last};
+ auto __end = __first;
+ return {__first, ++__end};
}
}
@@ -461,7 +460,8 @@ namespace ranges
return {__first - __count, __first};
}
}
- return {__last, __last};
+ auto __i = __first + __tail_size;
+ return {__i, __i};
}
else
{
@@ -480,10 +480,10 @@ namespace ranges
if (__n == 1)
return {__first, __i};
if (__i == __last)
- return {__last, __last};
+ return {__i, __i};
__first = ranges::find_if(++__i, __last, __value_comp, __proj);
}
- return {__last, __last};
+ return {__first, __first};
}
}
@@ -509,11 +509,11 @@ namespace ranges
_Iter2 __first2, _Sent2 __last2,
_Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
{
+ auto __i = ranges::next(__first1, __last1);
if (__first2 == __last2)
- return {__last1, __last1};
+ return {__i, __i};
- auto __res_first = __last1;
- auto __res_last = __last1;
+ auto __res_first = __i, __res_last = __i;
for (;;)
{
auto __new_range = ranges::search(__first1, __last1,
@@ -546,17 +546,19 @@ namespace ranges
if constexpr (bidirectional_iterator<_Iter1>
&& bidirectional_iterator<_Iter2>)
{
+ auto __i1 = ranges::next(__first1, __last1);
+ auto __i2 = ranges::next(__first2, __last2);
auto __rresult
- = ranges::search(reverse_iterator<_Iter1>{__last1},
+ = ranges::search(reverse_iterator<_Iter1>{__i1},
reverse_iterator<_Iter1>{__first1},
- reverse_iterator<_Iter2>{__last2},
+ reverse_iterator<_Iter2>{__i2},
reverse_iterator<_Iter2>{__first2},
std::move(__pred),
std::move(__proj1), std::move(__proj2));
auto __result_first = ranges::end(__rresult).base();
auto __result_last = ranges::begin(__rresult).base();
if (__result_last == __first1)
- return {__last1, __last1};
+ return {__i1, __i1};
else
return {__result_first, __result_last};
}
@@ -591,7 +593,7 @@ namespace ranges
_Pred __pred = {}, _Proj __proj = {})
{
if (__first == __last)
- return __last;
+ return __first;
auto __next = __first;
auto __proj_first = std::__invoke(__proj, *__first);
while (++__next != __last)
@@ -602,7 +604,7 @@ namespace ranges
__first = __next;
__proj_first = std::move(__proj_next);
}
- return __last;
+ return __next;
}
template<forward_range _Range, typename _Proj = identity,
@@ -632,8 +634,8 @@ namespace ranges
&& sized_sentinel_for<_Sent2, _Iter2>);
if constexpr (__sized_iters)
{
- auto __d1 = std::distance(__first1, __last1);
- auto __d2 = std::distance(__first2, __last2);
+ auto __d1 = ranges::distance(__first1, __last1);
+ auto __d2 = ranges::distance(__first2, __last2);
if (__d1 != __d2)
return false;
}
@@ -654,8 +656,8 @@ namespace ranges
}
else
{
- auto __d1 = std::distance(__first1, __last1);
- auto __d2 = std::distance(__first2, __last2);
+ auto __d1 = ranges::distance(__first1, __last1);
+ auto __d2 = ranges::distance(__first2, __last2);
if (__d1 == 0 && __d2 == 0)
return true;
if (__d1 != __d2)
@@ -1286,7 +1288,7 @@ namespace ranges
{
__first = ranges::find_if(__first, __last, __pred, __proj);
if (__first == __last)
- return {__first, __last};
+ return {__first, __first};
auto __result = __first;
++__first;
@@ -1297,7 +1299,7 @@ namespace ranges
++__result;
}
- return {__result, __last};
+ return {__result, __first};
}
template<forward_range _Range, class _Proj = identity,
@@ -1354,7 +1356,7 @@ namespace ranges
*__result = *__first;
++__result;
}
- return {__last, __result};
+ return {__first, __result};
}
template<input_range _Range, weakly_incrementable _Out,
@@ -1389,7 +1391,7 @@ namespace ranges
*__result = *__first;
++__result;
}
- return {__last, __result};
+ return {__first, __result};
}
template<input_range _Range, weakly_incrementable _Out,
@@ -1415,7 +1417,7 @@ namespace ranges
{
__first = ranges::adjacent_find(__first, __last, __comp, __proj);
if (__first == __last)
- return {__last, __last};
+ return {__first, __first};
auto __dest = __first;
++__first;
@@ -1424,7 +1426,7 @@ namespace ranges
std::__invoke(__proj, *__dest),
std::__invoke(__proj, *__first)))
*++__dest = std::move(*__first);
- return {++__dest, __last};
+ return {++__dest, __first};
}
template<forward_range _Range, class _Proj = identity,
@@ -1455,7 +1457,7 @@ namespace ranges
_Comp __comp = {}, _Proj __proj = {})
{
if (__first == __last)
- return {__last, __result};
+ return {__first, __result};
if constexpr (forward_iterator<_Iter>)
{
@@ -1469,7 +1471,7 @@ namespace ranges
__first = __next;
*++__result = *__first;
}
- return {__last, ++__result};
+ return {__next, ++__result};
}
else if constexpr (input_iterator<_Out>
&& same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
@@ -1480,7 +1482,7 @@ namespace ranges
std::__invoke(__proj, *__result),
std::__invoke(__proj, *__first)))
*++__result = *__first;
- return {__last, ++__result};
+ return {__first, ++__result};
}
else // indirectly_copyable_storable<_Iter, _Out>
{
@@ -1496,7 +1498,7 @@ namespace ranges
*++__result = __value;
}
}
- return {__last, ++__result};
+ return {__first, ++__result};
}
}
diff --git a/libstdc++-v3/testsuite/25_algorithms/find_end/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/find_end/constrained.cc
index 70b44bb..b51e4a7 100644
--- a/libstdc++-v3/testsuite/25_algorithms/find_end/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/find_end/constrained.cc
@@ -26,6 +26,7 @@ using __gnu_test::test_container;
using __gnu_test::test_range;
using __gnu_test::input_iterator_wrapper;
using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::bidirectional_iterator_wrapper;
namespace ranges = std::ranges;
@@ -54,6 +55,15 @@ test01()
VERIFY( std::get<0>(res) == ranges::begin(r)
&& std::get<1>(res) == ranges::end(r) );
}
+
+ {
+ test_range<X, bidirectional_iterator_wrapper> r(x);
+ auto res = ranges::find_end(r, y, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(r) );
+ res = ranges::find_end(r, r, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res) == ranges::begin(r)
+ && std::get<1>(res) == ranges::end(r) );
+ }
}
void
diff --git a/libstdc++-v3/testsuite/25_algorithms/remove_if/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/remove_if/constrained.cc
index 25a99a0..1abc231 100644
--- a/libstdc++-v3/testsuite/25_algorithms/remove_if/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/remove_if/constrained.cc
@@ -70,7 +70,7 @@ test04()
{
X x[8] = { {0}, {1}, {0}, {1}, {0}, {0}, {1}, {1} };
const int y[4] = { 0, 0, 0, 0 };
- test_container<X, forward_iterator_wrapper> c(x);
+ test_range<X, forward_iterator_wrapper> c(x);
auto res = ranges::remove_if(c, [] (int a) { return a == 1; }, &X::i);
VERIFY( res.begin().ptr == x+4 && res.end().ptr == x+8 );
VERIFY( ranges::equal(x, x+4, y, y+4, {}, &X::i) );
diff --git a/libstdc++-v3/testsuite/25_algorithms/search_n/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/search_n/constrained.cc
index de9b171..c1ac6da 100644
--- a/libstdc++-v3/testsuite/25_algorithms/search_n/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/search_n/constrained.cc
@@ -51,6 +51,9 @@ test01()
test_range<int, forward_iterator_wrapper> ry(y);
auto res3 = ranges::search_n(ry, 3, 2);
VERIFY( *res3.begin() == 2 && *res3.end() == 5 );
+
+ auto res4 = ranges::search_n(ry, 1, 8);
+ VERIFY( res4.begin().ptr == y+2 && res4.end().ptr == y+3 );
}
void
More information about the Libstdc++-cvs
mailing list