Skip to content

Commit bd1bfa3

Browse files
committed
Add the version of find_backward() that is actually going in to the standard
-- find_last().
1 parent da8ea58 commit bd1bfa3

File tree

6 files changed

+906
-0
lines changed

6 files changed

+906
-0
lines changed

Diff for: doc/algorithm.qbk

+9
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,15 @@ Apply a functor to the elements of a sequence
110110

111111
[endsect:CXX17]
112112

113+
[section:CXX23 C++23 Algorithms]
114+
115+
[section:CXX23_inner_algorithms]
116+
117+
[include find_last.qbk]
118+
119+
[endsect:CXX23_inner_algorithms]
120+
121+
[endsect:CXX23]
113122

114123
[section:Misc Other Algorithms]
115124

Diff for: doc/find_last.qbk

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
[/ File find_last.qbk]
2+
3+
[section:find_last find_last, find_last_if, find_last_if_not ]
4+
5+
[/license
6+
Copyright (c) 2022 T. Zachary Laine
7+
8+
Distributed under the Boost Software License, Version 1.0.
9+
(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10+
]
11+
12+
The header file 'find_last.hpp' contains variants of the stl algorithm
13+
`find`. These variants are like `find`, except that they find the last
14+
instance of an element instead of the first.
15+
16+
The functions in this header are as close to the ones in C++23's `std::ranges`
17+
namespace as possible. In C++20 builds, they are constrained exactly as the
18+
standard does it. They each return a `boost::algorithm::subrange`, which is a
19+
mostly-API-compatible version of `std::ranges::subrange`. It's differences
20+
from the C++20 `subrange` are that it does not support sized ranges, and that
21+
it cannot be implicitly converted to a pair-like type.
22+
23+
[heading interface]
24+
25+
template<typename ForwardIterator, typename Sentinel, typename T, typename Proj = identity>
26+
BOOST_CXX14_CONSTEXPR subrange<ForwardIterator>
27+
find_last(ForwardIterator first, Sentinel last, const T & value, Proj proj = {})
28+
29+
template<typename R, typename T, typename Proj = identity>
30+
BOOST_CXX14_CONSTEXPR subrange<iterator_t<R>>
31+
find_last(R && r, const T & value, Proj proj = {})
32+
33+
These overloads of `find_last` return a subrange `[it, end)`, where `it` is
34+
the position of the last element that is equal to `x` in the given range, and
35+
`end` is the end of the given range.
36+
37+
template<typename ForwardIterator, typename Sentinel, typename Pred, typename Proj = identity>
38+
BOOST_CXX14_CONSTEXPR subrange<ForwardIterator>
39+
find_last_if(ForwardIterator first, Sentinel last, Pred pred, Proj proj = {})
40+
41+
template<typename R, typename Pred, typename Proj = identity>
42+
BOOST_CXX14_CONSTEXPR subrange<iterator_t<R>>
43+
find_last_if(R && r, Pred pred, Proj proj = {})
44+
45+
These overloads of `find_if_last` return a subrange `[it, end)`, where `it` is
46+
the position of the last element for which `pred` returns `true` in the given
47+
range, and `end` is the end of the given range.
48+
49+
template<typename ForwardIterator, typename Sentinel, typename Pred, typename Proj = identity>
50+
BOOST_CXX14_CONSTEXPR subrange<ForwardIterator>
51+
find_last_if_not(ForwardIterator first, Sentinel last, Pred pred, Proj proj = {})
52+
53+
template<typename R, typename Pred, typename Proj = identity>
54+
BOOST_CXX14_CONSTEXPR subrange<iterator_t<R>>
55+
find_last_if_not(R && r, Pred pred, Proj proj = {})
56+
57+
These overloads of `find_if_last` return a subrange `[it, end)`, where `it` is
58+
the position of the last element for which `pred` returns `false` in the given
59+
range, and `end` is the end of the given range.
60+
61+
[heading Examples]
62+
63+
Given the container `c1` containing `{ 2, 1, 2 }`, then
64+
65+
find_last ( c1.begin(), c1.end(), 2 ) --> --c1.end()
66+
find_last ( c1.begin(), c1.end(), 3 ) --> c1.end()
67+
find_last_if ( c1.begin(), c1.end(), [](int i) {return i == 2;} ) --> --c1.end()
68+
find_last_if ( c1.begin(), c1.end(), [](int i) {return i == 3;} ) --> c1.end()
69+
find_last_if_not ( c1.begin(), c1.end(), [](int i) {return i == 2;} ) --> std::prev(c1.end(), 2)
70+
find_last_if_not ( c1.begin(), c1.end(), [](int i) {return i == 1;} ) --> c1.end()
71+
72+
[heading Iterator Requirements]
73+
74+
All variants work on forward iterators.
75+
76+
[heading Complexity]
77+
78+
Linear.
79+
80+
[heading Exception Safety]
81+
82+
All of the variants take their parameters by value and do not depend upon any
83+
global state. Therefore, all the routines in this file provide the strong
84+
exception guarantee.
85+
86+
[heading Notes]
87+
88+
All variants are `constexpr` in C++14 or later.
89+
90+
[endsect]
91+
92+
[/ File find_last.qbk
93+
Copyright 2022 T. Zachary Laine
94+
Distributed under the Boost Software License, Version 1.0.
95+
(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
96+
]

Diff for: include/boost/algorithm/cxx20_helper.hpp

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
Copyright (c) T. Zachary Laine 2022.
3+
4+
Distributed under the Boost Software License, Version 1.0. (See accompanying
5+
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
6+
*/
7+
#ifndef BOOST_ALGORITHM_CXX20_HELPER_HPP
8+
#define BOOST_ALGORITHM_CXX20_HELPER_HPP
9+
10+
#include <boost/config.hpp>
11+
#include <boost/stl_interfaces/view_interface.hpp>
12+
#include <boost/range/begin.hpp>
13+
#include <boost/range/end.hpp>
14+
15+
#include <type_traits>
16+
17+
18+
namespace boost { namespace algorithm {
19+
20+
struct identity
21+
{
22+
template<typename T>
23+
BOOST_CXX14_CONSTEXPR T && operator()(T && x) const noexcept
24+
{
25+
return (T &&) x;
26+
}
27+
};
28+
29+
#if defined(__cpp_lib_concepts)
30+
template<typename R>
31+
using iterator_t = std::ranges::iterator_t<R>;
32+
template<typename R>
33+
using sentinel_t = std::ranges::sentinel_t<R>;
34+
#else
35+
template<typename R>
36+
using iterator_t = decltype(boost::begin(std::declval<R>()));
37+
template<typename R>
38+
using sentinel_t = decltype(boost::end(std::declval<R>()));
39+
#endif
40+
41+
template<typename Iterator, typename Sentinel = Iterator>
42+
struct subrange
43+
: stl_interfaces::view_interface<subrange<Iterator, Sentinel>>
44+
{
45+
BOOST_CXX14_CONSTEXPR subrange() = default;
46+
BOOST_CXX14_CONSTEXPR subrange(Iterator first, Sentinel last) :
47+
first_(first), last_(last)
48+
{}
49+
template<typename R>
50+
BOOST_CXX14_CONSTEXPR explicit subrange(const R & r) :
51+
first_(boost::begin(r)), last_(boost::end(r))
52+
{}
53+
54+
BOOST_CXX14_CONSTEXPR Iterator begin() const { return first_; }
55+
BOOST_CXX14_CONSTEXPR Sentinel end() const { return last_; }
56+
57+
[[nodiscard]] BOOST_CXX14_CONSTEXPR subrange
58+
next(std::ptrdiff_t n = 1) const
59+
{
60+
return subrange{std::next(first_), last_};
61+
}
62+
[[nodiscard]] BOOST_CXX14_CONSTEXPR subrange
63+
prev(std::ptrdiff_t n = 1) const
64+
{
65+
return subrange{std::prev(first_), last_};
66+
}
67+
68+
BOOST_CXX14_CONSTEXPR subrange & advance(std::ptrdiff_t n)
69+
{
70+
std::advance(first_, n);
71+
return *this;
72+
}
73+
74+
template<
75+
typename Iterator2,
76+
typename Sentinel2,
77+
typename Enable = std::enable_if_t<
78+
std::is_convertible<Iterator, Iterator2>::value &&
79+
std::is_convertible<Sentinel, Sentinel2>::value>>
80+
BOOST_CXX14_CONSTEXPR operator subrange<Iterator2, Sentinel2>() const
81+
{
82+
return {first_, last_};
83+
}
84+
85+
private:
86+
Iterator first_;
87+
Sentinel last_;
88+
};
89+
90+
}} // namespace boost and algorithm
91+
92+
#endif // BOOST_ALGORITHM_CXX20_HELPER

0 commit comments

Comments
 (0)