From c5c5d24ff3984c18bea795b4638b0f7f62680056 Mon Sep 17 00:00:00 2001 From: Zach Laine Date: Sat, 12 May 2018 16:03:41 -0500 Subject: [PATCH] Add range-based overloads of find*_backward(). --- doc/find_backward.qbk | 32 ++++++-- doc/find_not.qbk | 10 ++- include/boost/algorithm/find_backward.hpp | 43 ++++++++++- test/find_backward_test.cpp | 93 +++++++++++++++++++++++ 4 files changed, 163 insertions(+), 15 deletions(-) diff --git a/doc/find_backward.qbk b/doc/find_backward.qbk index 820a3fc..81cec0c 100644 --- a/doc/find_backward.qbk +++ b/doc/find_backward.qbk @@ -42,26 +42,38 @@ that the member requires. template BidiIter find_backward(BidiIter first, BidiIter last, T const & x); -The function `find_backward` returns an iterator to the last element of -`[first, last)` that is equal to `x`. + template + boost::range_iterator 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 BidiIter find_not_backward(BidiIter first, BidiIter last, T const & x); -The function `find_not_backward` returns an iterator to the last element of -`[first, last)` that is not equal to `x`. + template + boost::range_iterator 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 BidiIter find_if_backward(BidiIter first, BidiIter last, Pred p); -The function `find_if_backward` returns an iterator to the last element of -`[first, last)` for which `pred` returns `true`. + template + boost::range_iterator 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 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 -`[first, last)` for which `pred` returns `false`. + template + boost::range_iterator 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] @@ -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 exception guarantee. +[heading Notes] + +All variants are `constexpr` in C++14 or later. + [endsect] [/ File equal.qbk diff --git a/doc/find_not.qbk b/doc/find_not.qbk index 8d26185..a5a17cf 100644 --- a/doc/find_not.qbk +++ b/doc/find_not.qbk @@ -43,10 +43,10 @@ our find condition. InputIter find_not(InputIter first, Sentinel last, T const & x); template - typename boost::range_iterator::type find_not(Range & r, T const & x); + boost::range_iterator find_not(Range & r, T const & x); -The function `find_not` returns the first value in the sequence `[first, -last)` that is not equal to `x`. +The function `find_not` returns the first value that is not equal to `x` in +the sequence `[first, last)` or `r`, respectively. [heading Examples] @@ -72,6 +72,10 @@ Linear. `find_not` takes its parameters by value and do not depend upon any global state. Therefore, it provides the strong exception guarantee. +[heading Notes] + +`constexpr` in C++14 or later. + [endsect] [/ File equal.qbk diff --git a/include/boost/algorithm/find_backward.hpp b/include/boost/algorithm/find_backward.hpp index 1a2bff7..ffa7e03 100644 --- a/include/boost/algorithm/find_backward.hpp +++ b/include/boost/algorithm/find_backward.hpp @@ -8,13 +8,17 @@ #define BOOST_ALGORITHM_FIND_BACKWARD_HPP #include +#include +#include + #include namespace boost { namespace algorithm { template -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; while (it != first) { @@ -24,8 +28,16 @@ BOOST_CXX14_CONSTEXPR BidiIter find_backward(BidiIter first, BidiIter last, T co return last; } +template +BOOST_CXX14_CONSTEXPR +typename boost::range_iterator::type find_backward(Range & range, T const & x) +{ + return ::boost::algorithm::find_backward(boost::begin(range), boost::end(range), x); +} + template -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; while (it != first) { @@ -35,8 +47,16 @@ BOOST_CXX14_CONSTEXPR BidiIter find_not_backward(BidiIter first, BidiIter last, return last; } +template +BOOST_CXX14_CONSTEXPR +typename boost::range_iterator::type find_not_backward(Range & range, T const & x) +{ + return ::boost::algorithm::find_not_backward(boost::begin(range), boost::end(range), x); +} + template -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; while (it != first) { @@ -46,8 +66,16 @@ BOOST_CXX14_CONSTEXPR BidiIter find_if_backward(BidiIter first, BidiIter last, P return last; } +template +BOOST_CXX14_CONSTEXPR +typename boost::range_iterator::type find_if_backward(Range & range, Pred p) +{ + return ::boost::algorithm::find_if_backward(boost::begin(range), boost::end(range), p); +} + template -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; while (it != first) { @@ -57,6 +85,13 @@ BOOST_CXX14_CONSTEXPR BidiIter find_if_not_backward(BidiIter first, BidiIter las return last; } +template +BOOST_CXX14_CONSTEXPR +typename boost::range_iterator::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 #endif // BOOST_ALGORITHM_FIND_BACKWARD_HPP diff --git a/test/find_backward_test.cpp b/test/find_backward_test.cpp index 9a51281..721c728 100644 --- a/test/find_backward_test.cpp +++ b/test/find_backward_test.cpp @@ -43,12 +43,21 @@ BOOST_CXX14_CONSTEXPR bool check_constexpr_backward() const int* start = ba::find_backward(from, to, 1); // stops on first 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 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 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; } @@ -69,6 +78,12 @@ void test_find_backward() v1.size() - 1); BOOST_CHECK_EQUAL( 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. @@ -87,6 +102,12 @@ void test_find_backward() l1.size() - 1); BOOST_CHECK_EQUAL( 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(); @@ -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 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 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 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; } @@ -141,6 +171,14 @@ void test_find_if_backward() dist( ba::find_if_backward(v1.begin(), v1.end(), equals(v1.front()))), 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. @@ -163,6 +201,14 @@ void test_find_if_backward() dist( ba::find_if_backward(l1.begin(), l1.end(), equals(l1.front()))), 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(); @@ -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 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 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 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; } @@ -219,6 +274,16 @@ void test_find_if_not_backward() dist(ba::find_if_not_backward( v1.begin(), v1.end(), not_equals(v1.front()))), 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. @@ -243,6 +308,16 @@ void test_find_if_not_backward() dist(ba::find_if_not_backward( l1.begin(), l1.end(), not_equals(l1.front()))), 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(); @@ -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 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* end = ba::find_not_backward(in_data_2, in_data_2 + 5, 6); // stops on the end 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; } @@ -286,9 +367,15 @@ void test_find_not_backward() dist(ba::find_not_backward(v1.begin(), v1.end(), 2)), 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); BOOST_CHECK_EQUAL( 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. @@ -309,9 +396,15 @@ void test_find_not_backward() dist(ba::find_not_backward(l1.begin(), l1.end(), 2)), 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); BOOST_CHECK_EQUAL( 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();