Add range-based overloads of find*_backward().

This commit is contained in:
Zach Laine
2018-05-12 16:03:41 -05:00
parent 6c68cf8624
commit c5c5d24ff3
4 changed files with 163 additions and 15 deletions

View File

@ -42,26 +42,38 @@ that the member requires.
template<typename BidiIter, typename T> template<typename BidiIter, typename T>
BidiIter find_backward(BidiIter first, BidiIter last, T const & x); BidiIter find_backward(BidiIter first, BidiIter last, T const & x);
The function `find_backward` returns an iterator to the last element of template<typename Range, typename T>
`[first, last)` that is equal to `x`. boost::range_iterator<Range> find_backward(Range & range, T const & x);
The function `find_backward` returns an iterator to the last element that is
equal to `x` in `[first, last)` or `r`, respectively.
template<typename BidiIter, typename T> template<typename BidiIter, typename T>
BidiIter find_not_backward(BidiIter first, BidiIter last, T const & x); BidiIter find_not_backward(BidiIter first, BidiIter last, T const & x);
The function `find_not_backward` returns an iterator to the last element of template<typename Range, typename T>
`[first, last)` that is not equal to `x`. boost::range_iterator<Range> find_not_backward(Range & range, T const & x);
The function `find_not_backward` returns an iterator to the last element that
is not equal to `x` in `[first, last)` or `r`, respectively.
template<typename BidiIter, typename Pred> template<typename BidiIter, typename Pred>
BidiIter find_if_backward(BidiIter first, BidiIter last, Pred p); BidiIter find_if_backward(BidiIter first, BidiIter last, Pred p);
The function `find_if_backward` returns an iterator to the last element of template<typename Range, typename Pred>
`[first, last)` for which `pred` returns `true`. boost::range_iterator<Range> find_if_backward(Range & range, Pred p);
The function `find_if_backward` returns an iterator to the last element for
which `pred` returns `true` in `[first, last)` or `r`, respectively.
template<typename BidiIter, typename Pred> template<typename BidiIter, typename Pred>
BidiIter find_if_not_backward(BidiIter first, BidiIter last, Pred p); BidiIter find_if_not_backward(BidiIter first, BidiIter last, Pred p);
The function `find_if_not_backward` returns an iterator to the last element of template<typename Range, typename Pred>
`[first, last)` for which `pred` returns `false`. boost::range_iterator<Range> find_if_not_backward(Range & range, Pred p);
The function `find_if_not_backward` returns an iterator to the last element
for which `pred` returns `false` in `[first, last)` or `r`, respectively.
[heading Examples] [heading Examples]
@ -90,6 +102,10 @@ All of the variants take their parameters by value and do not depend upon any
global state. Therefore, all the routines in this file provide the strong global state. Therefore, all the routines in this file provide the strong
exception guarantee. exception guarantee.
[heading Notes]
All variants are `constexpr` in C++14 or later.
[endsect] [endsect]
[/ File equal.qbk [/ File equal.qbk

View File

@ -43,10 +43,10 @@ our find condition.
InputIter find_not(InputIter first, Sentinel last, T const & x); InputIter find_not(InputIter first, Sentinel last, T const & x);
template<typename Range, typename T> template<typename Range, typename T>
typename boost::range_iterator<Range>::type find_not(Range & r, T const & x); boost::range_iterator<Range> find_not(Range & r, T const & x);
The function `find_not` returns the first value in the sequence `[first, The function `find_not` returns the first value that is not equal to `x` in
last)` that is not equal to `x`. the sequence `[first, last)` or `r`, respectively.
[heading Examples] [heading Examples]
@ -72,6 +72,10 @@ Linear.
`find_not` takes its parameters by value and do not depend upon any global `find_not` takes its parameters by value and do not depend upon any global
state. Therefore, it provides the strong exception guarantee. state. Therefore, it provides the strong exception guarantee.
[heading Notes]
`constexpr` in C++14 or later.
[endsect] [endsect]
[/ File equal.qbk [/ File equal.qbk

View File

@ -8,13 +8,17 @@
#define BOOST_ALGORITHM_FIND_BACKWARD_HPP #define BOOST_ALGORITHM_FIND_BACKWARD_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <utility> #include <utility>
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
template<typename BidiIter, typename T> template<typename BidiIter, typename T>
BOOST_CXX14_CONSTEXPR BidiIter find_backward(BidiIter first, BidiIter last, T const & x) BOOST_CXX14_CONSTEXPR
BidiIter find_backward(BidiIter first, BidiIter last, T const & x)
{ {
BidiIter it = last; BidiIter it = last;
while (it != first) { while (it != first) {
@ -24,8 +28,16 @@ BOOST_CXX14_CONSTEXPR BidiIter find_backward(BidiIter first, BidiIter last, T co
return last; return last;
} }
template<typename Range, typename T>
BOOST_CXX14_CONSTEXPR
typename boost::range_iterator<Range>::type find_backward(Range & range, T const & x)
{
return ::boost::algorithm::find_backward(boost::begin(range), boost::end(range), x);
}
template<typename BidiIter, typename T> template<typename BidiIter, typename T>
BOOST_CXX14_CONSTEXPR BidiIter find_not_backward(BidiIter first, BidiIter last, T const & x) BOOST_CXX14_CONSTEXPR
BidiIter find_not_backward(BidiIter first, BidiIter last, T const & x)
{ {
BidiIter it = last; BidiIter it = last;
while (it != first) { while (it != first) {
@ -35,8 +47,16 @@ BOOST_CXX14_CONSTEXPR BidiIter find_not_backward(BidiIter first, BidiIter last,
return last; return last;
} }
template<typename Range, typename T>
BOOST_CXX14_CONSTEXPR
typename boost::range_iterator<Range>::type find_not_backward(Range & range, T const & x)
{
return ::boost::algorithm::find_not_backward(boost::begin(range), boost::end(range), x);
}
template<typename BidiIter, typename Pred> template<typename BidiIter, typename Pred>
BOOST_CXX14_CONSTEXPR BidiIter find_if_backward(BidiIter first, BidiIter last, Pred p) BOOST_CXX14_CONSTEXPR
BidiIter find_if_backward(BidiIter first, BidiIter last, Pred p)
{ {
BidiIter it = last; BidiIter it = last;
while (it != first) { while (it != first) {
@ -46,8 +66,16 @@ BOOST_CXX14_CONSTEXPR BidiIter find_if_backward(BidiIter first, BidiIter last, P
return last; return last;
} }
template<typename Range, typename Pred>
BOOST_CXX14_CONSTEXPR
typename boost::range_iterator<Range>::type find_if_backward(Range & range, Pred p)
{
return ::boost::algorithm::find_if_backward(boost::begin(range), boost::end(range), p);
}
template<typename BidiIter, typename Pred> template<typename BidiIter, typename Pred>
BOOST_CXX14_CONSTEXPR BidiIter find_if_not_backward(BidiIter first, BidiIter last, Pred p) BOOST_CXX14_CONSTEXPR
BidiIter find_if_not_backward(BidiIter first, BidiIter last, Pred p)
{ {
BidiIter it = last; BidiIter it = last;
while (it != first) { while (it != first) {
@ -57,6 +85,13 @@ BOOST_CXX14_CONSTEXPR BidiIter find_if_not_backward(BidiIter first, BidiIter las
return last; return last;
} }
template<typename Range, typename Pred>
BOOST_CXX14_CONSTEXPR
typename boost::range_iterator<Range>::type find_if_not_backward(Range & range, Pred p)
{
return ::boost::algorithm::find_if_not_backward(boost::begin(range), boost::end(range), p);
}
}} // namespace boost and algorithm }} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_FIND_BACKWARD_HPP #endif // BOOST_ALGORITHM_FIND_BACKWARD_HPP

View File

@ -43,12 +43,21 @@ BOOST_CXX14_CONSTEXPR bool check_constexpr_backward()
const int* start = ba::find_backward(from, to, 1); // stops on first const int* start = ba::find_backward(from, to, 1); // stops on first
res = (res && start == from); res = (res && start == from);
start = ba::find_backward(in_data, 1); // stops on first
res = (res && start == from);
const int* end = ba::find_backward(from, to, 6); // stops on the end const int* end = ba::find_backward(from, to, 6); // stops on the end
res = (res && end == to); res = (res && end == to);
end = ba::find_backward(in_data, 6); // stops on the end
res = (res && end == to);
const int* three = ba::find_backward(from, to, 3); // stops on third element const int* three = ba::find_backward(from, to, 3); // stops on third element
res = (res && three == in_data + 2); res = (res && three == in_data + 2);
three = ba::find_backward(in_data, 3); // stops on third element
res = (res && three == in_data + 2);
return res; return res;
} }
@ -69,6 +78,12 @@ void test_find_backward()
v1.size() - 1); v1.size() - 1);
BOOST_CHECK_EQUAL( BOOST_CHECK_EQUAL(
dist(ba::find_backward(v1.begin(), v1.end(), v1.front())), 0); dist(ba::find_backward(v1.begin(), v1.end(), v1.front())), 0);
BOOST_CHECK_EQUAL(dist(ba::find_backward(v1, 0)), v1.size());
BOOST_CHECK_EQUAL(dist(ba::find_backward(v1, 100)), v1.size());
BOOST_CHECK_EQUAL(
dist(ba::find_backward(v1, v1.back())), v1.size() - 1);
BOOST_CHECK_EQUAL(dist(ba::find_backward(v1, v1.front())), 0);
} }
// With bidirectional iterators. // With bidirectional iterators.
@ -87,6 +102,12 @@ void test_find_backward()
l1.size() - 1); l1.size() - 1);
BOOST_CHECK_EQUAL( BOOST_CHECK_EQUAL(
dist(ba::find_backward(l1.begin(), l1.end(), l1.front())), 0); dist(ba::find_backward(l1.begin(), l1.end(), l1.front())), 0);
BOOST_CHECK_EQUAL(dist(ba::find_backward(l1, 0)), l1.size());
BOOST_CHECK_EQUAL(dist(ba::find_backward(l1, 100)), l1.size());
BOOST_CHECK_EQUAL(
dist(ba::find_backward(l1, l1.back())), l1.size() - 1);
BOOST_CHECK_EQUAL(dist(ba::find_backward(l1, l1.front())), 0);
} }
BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_backward(); BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_backward();
@ -111,12 +132,21 @@ BOOST_CXX14_CONSTEXPR bool check_constexpr_if_backward()
const int* start = ba::find_if_backward(from, to, equals(1)); // stops on first const int* start = ba::find_if_backward(from, to, equals(1)); // stops on first
res = (res && start == from); res = (res && start == from);
start = ba::find_if_backward(in_data, equals(1)); // stops on first
res = (res && start == from);
const int* end = ba::find_if_backward(from, to, equals(6)); // stops on the end const int* end = ba::find_if_backward(from, to, equals(6)); // stops on the end
res = (res && end == to); res = (res && end == to);
end = ba::find_if_backward(in_data, equals(6)); // stops on the end
res = (res && end == to);
const int* three = ba::find_if_backward(from, to, equals(3)); // stops on third element const int* three = ba::find_if_backward(from, to, equals(3)); // stops on third element
res = (res && three == in_data + 2); res = (res && three == in_data + 2);
three = ba::find_if_backward(in_data, equals(3)); // stops on third element
res = (res && three == in_data + 2);
return res; return res;
} }
@ -141,6 +171,14 @@ void test_find_if_backward()
dist( dist(
ba::find_if_backward(v1.begin(), v1.end(), equals(v1.front()))), ba::find_if_backward(v1.begin(), v1.end(), equals(v1.front()))),
0); 0);
BOOST_CHECK_EQUAL(dist(ba::find_if_backward(v1, equals(0))), v1.size());
BOOST_CHECK_EQUAL(
dist(ba::find_if_backward(v1, equals(100))), v1.size());
BOOST_CHECK_EQUAL(
dist(ba::find_if_backward(v1, equals(v1.back()))), v1.size() - 1);
BOOST_CHECK_EQUAL(
dist(ba::find_if_backward(v1, equals(v1.front()))), 0);
} }
// With bidirectional iterators. // With bidirectional iterators.
@ -163,6 +201,14 @@ void test_find_if_backward()
dist( dist(
ba::find_if_backward(l1.begin(), l1.end(), equals(l1.front()))), ba::find_if_backward(l1.begin(), l1.end(), equals(l1.front()))),
0); 0);
BOOST_CHECK_EQUAL(dist(ba::find_if_backward(l1, equals(0))), l1.size());
BOOST_CHECK_EQUAL(
dist(ba::find_if_backward(l1, equals(100))), l1.size());
BOOST_CHECK_EQUAL(
dist(ba::find_if_backward(l1, equals(l1.back()))), l1.size() - 1);
BOOST_CHECK_EQUAL(
dist(ba::find_if_backward(l1, equals(l1.front()))), 0);
} }
BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_if_backward(); BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_if_backward();
@ -187,12 +233,21 @@ BOOST_CXX14_CONSTEXPR bool check_constexpr_if_not_backward()
const int* start = ba::find_if_not_backward(from, to, not_equals(1)); // stops on first const int* start = ba::find_if_not_backward(from, to, not_equals(1)); // stops on first
res = (res && start == from); res = (res && start == from);
start = ba::find_if_not_backward(in_data, not_equals(1)); // stops on first
res = (res && start == from);
const int* end = ba::find_if_not_backward(from, to, not_equals(6)); // stops on the end const int* end = ba::find_if_not_backward(from, to, not_equals(6)); // stops on the end
res = (res && end == to); res = (res && end == to);
end = ba::find_if_not_backward(in_data, not_equals(6)); // stops on the end
res = (res && end == to);
const int* three = ba::find_if_not_backward(from, to, not_equals(3)); // stops on third element const int* three = ba::find_if_not_backward(from, to, not_equals(3)); // stops on third element
res = (res && three == in_data + 2); res = (res && three == in_data + 2);
three = ba::find_if_not_backward(in_data, not_equals(3)); // stops on third element
res = (res && three == in_data + 2);
return res; return res;
} }
@ -219,6 +274,16 @@ void test_find_if_not_backward()
dist(ba::find_if_not_backward( dist(ba::find_if_not_backward(
v1.begin(), v1.end(), not_equals(v1.front()))), v1.begin(), v1.end(), not_equals(v1.front()))),
0); 0);
BOOST_CHECK_EQUAL(
dist(ba::find_if_not_backward(v1, not_equals(0))), v1.size());
BOOST_CHECK_EQUAL(
dist(ba::find_if_not_backward(v1, not_equals(100))), v1.size());
BOOST_CHECK_EQUAL(
dist(ba::find_if_not_backward(v1, not_equals(v1.back()))),
v1.size() - 1);
BOOST_CHECK_EQUAL(
dist(ba::find_if_not_backward(v1, not_equals(v1.front()))), 0);
} }
// With bidirectional iterators. // With bidirectional iterators.
@ -243,6 +308,16 @@ void test_find_if_not_backward()
dist(ba::find_if_not_backward( dist(ba::find_if_not_backward(
l1.begin(), l1.end(), not_equals(l1.front()))), l1.begin(), l1.end(), not_equals(l1.front()))),
0); 0);
BOOST_CHECK_EQUAL(
dist(ba::find_if_not_backward(l1, not_equals(0))), l1.size());
BOOST_CHECK_EQUAL(
dist(ba::find_if_not_backward(l1, not_equals(100))), l1.size());
BOOST_CHECK_EQUAL(
dist(ba::find_if_not_backward(l1, not_equals(l1.back()))),
l1.size() - 1);
BOOST_CHECK_EQUAL(
dist(ba::find_if_not_backward(l1, not_equals(l1.front()))), 0);
} }
BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_if_not_backward(); BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_if_not_backward();
@ -260,10 +335,16 @@ BOOST_CXX14_CONSTEXPR bool check_constexpr_not_backward()
const int* start = ba::find_not_backward(from, to, 5); // stops on first const int* start = ba::find_not_backward(from, to, 5); // stops on first
res = (res && start == from); res = (res && start == from);
start = ba::find_not_backward(in_data, 5); // stops on first
res = (res && start == from);
const int in_data_2[] = {6, 6, 6, 6, 6}; const int in_data_2[] = {6, 6, 6, 6, 6};
const int* end = ba::find_not_backward(in_data_2, in_data_2 + 5, 6); // stops on the end const int* end = ba::find_not_backward(in_data_2, in_data_2 + 5, 6); // stops on the end
res = (res && end == in_data_2 + 5); res = (res && end == in_data_2 + 5);
end = ba::find_not_backward(in_data_2, 6); // stops on the end
res = (res && end == in_data_2 + 5);
return res; return res;
} }
@ -286,9 +367,15 @@ void test_find_not_backward()
dist(ba::find_not_backward(v1.begin(), v1.end(), 2)), dist(ba::find_not_backward(v1.begin(), v1.end(), 2)),
v1.size() - 1); v1.size() - 1);
BOOST_CHECK_EQUAL(dist(ba::find_not_backward(v1, 1)), 4);
BOOST_CHECK_EQUAL(dist(ba::find_not_backward(v1, 0)), v1.size() - 1);
BOOST_CHECK_EQUAL(dist(ba::find_not_backward(v1, 2)), v1.size() - 1);
v1.resize(5); v1.resize(5);
BOOST_CHECK_EQUAL( BOOST_CHECK_EQUAL(
dist(ba::find_not_backward(v1.begin(), v1.end(), 0)), v1.size()); dist(ba::find_not_backward(v1.begin(), v1.end(), 0)), v1.size());
BOOST_CHECK_EQUAL(dist(ba::find_not_backward(v1, 0)), v1.size());
} }
// With bidirectional iterators. // With bidirectional iterators.
@ -309,9 +396,15 @@ void test_find_not_backward()
dist(ba::find_not_backward(l1.begin(), l1.end(), 2)), dist(ba::find_not_backward(l1.begin(), l1.end(), 2)),
l1.size() - 1); l1.size() - 1);
BOOST_CHECK_EQUAL(dist(ba::find_not_backward(l1, 1)), 4);
BOOST_CHECK_EQUAL(dist(ba::find_not_backward(l1, 0)), l1.size() - 1);
BOOST_CHECK_EQUAL(dist(ba::find_not_backward(l1, 2)), l1.size() - 1);
l1.resize(5); l1.resize(5);
BOOST_CHECK_EQUAL( BOOST_CHECK_EQUAL(
dist(ba::find_not_backward(l1.begin(), l1.end(), 0)), l1.size()); dist(ba::find_not_backward(l1.begin(), l1.end(), 0)), l1.size());
BOOST_CHECK_EQUAL(dist(ba::find_not_backward(l1, 0)), l1.size());
} }
BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_not_backward(); BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_not_backward();