std::ranges::ends_with() algorithm
- od C++20
- Simplified
- Detailed
// (1)
constexpr bool ends_with( I1 first1, S1 last1, I2 first2, S2 last2,
Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );
// (2)
constexpr bool ends_with( R1&& r1, R2&& r2,
Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );
The type of arguments are generic and have the following constraints:
I1,I2-std::input_iteratorS1,S2-std::sentinel_for<I1>,std::sentinel_for<I2>Pred- (none)Proj1,Proj2- (none)- (2) -
R1,R2-std::ranges::input_range
The Pred template argumenth as a default type of ranges::equal_to for all overloads.
The Proj1 and Proj2 template arguments have a default type of std::identity for all overloads.
Additionally, each overload has the following constraints:
- (1):
(forward_iterator<I1> || sized_sentinel_for<S1, I1>)
&& (forward_iterator<I2> || sized_sentinel_for<S2, I2>)
&& indirectly_comparable<I1, I2, Pred, Proj1, Proj2>` - (2):
(ranges::forward_range<R1> || ranges::sized_range<R1>)
&& (ranges::forward_range<R2> || ranges::sized_range<R2>)
&& std::indirectly_comparable<ranges::iterator_t<R1>,
ranges::iterator_t<R2>,
Pred, Proj1, Proj2>
(The std:: namespace was ommitted here for readability)
// (1)
template<
std::input_iterator I1,
std::sentinel_for<I1> S1,
std::input_iterator I2,
std::sentinel_for<I2> S2,
class Pred = ranges::equal_to,
class Proj1 = std::identity, class Proj2 = std::identity
>
requires (std::forward_iterator<I1> || std::sized_sentinel_for<S1, I1>) &&
(std::forward_iterator<I2> || std::sized_sentinel_for<S2, I2>) &&
std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
constexpr bool ends_with( I1 first1, S1 last1, I2 first2, S2 last2,
Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );
// (2)
template<
ranges::input_range R1,
ranges::input_range R2,
class Pred = ranges::equal_to,
class Proj1 = std::identity, class Proj2 = std::identity
>
requires (ranges::forward_range<R1> || ranges::sized_range<R1>) &&
(ranges::forward_range<R2> || ranges::sized_range<R2>) &&
std::indirectly_comparable<ranges::iterator_t<R1>,
ranges::iterator_t<R2>,
Pred, Proj1, Proj2>
constexpr bool ends_with( R1&& r1, R2&& r2,
Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );
Checks whether the second range matches the suffix of the first range.
-
(1) Comparison is done by applying the binary predicate
predto elements in two ranges projected byproj1andproj2respectively. -
(2) Same as (1), but uses
r1as the first source range andr2as the second source range, as if usingranges::begin(r1)asfirst1,ranges::end(r1)aslast1,ranges::begin(r2)asfirst2, andranges::end(r2)aslast2.
The function-like entities described on this page are niebloids.
Parameters
first1 last1 | The range of elements to examine. |
r1 | The range of elements to examine. |
first2 last2 | The range of elements to be used as suffix. |
r2 | The range of elements to be used as suffix. |
pred | Binary predicate to compare the elements with. |
proj1 | Projection to apply to the elements in the first range. |
proj2 | Projection to apply to the elements in the second range. |
Return value
true if the second range matches the prefix of the first range, false otherwise.
More specifically:
Let N1 and N2 denote the size of ranges [first1; last1) and [first2; last2) respectively.
- If
N1 < N2, returnsfalse. - Otherwise, if every element in the range [
first2;last2) is equal to the corresponding element in [first1 + N1 - N2;last1) (compared usingpredafter projections), returnstrue.
Complexity
At most min(N1, N2) applications of the predicate and both projections. The predicate and both projections are not applied if N1 < N2
If both N1 and N2 can be calculated in constant time (i.e. both iterator-sentinel type pairs model sized_sentinel_for, or both range types model sized_range) and N1 < N2, the time complexity is constant.
Exceptions
(none)
Possible implementation
ends_with(1) and starts_with(2)
Examples
#include <algorithm>
#include <array>
#include <iostream>
int main()
{
std::cout
<< std::boolalpha
<< std::ranges::ends_with("static_cast", "cast") << '\n'
<< std::ranges::ends_with("const_cast", "cast") << '\n'
<< std::ranges::ends_with("reinterpret_cast", "cast") << '\n'
<< std::ranges::ends_with("dynamic_cast", "cast") << '\n'
<< std::ranges::ends_with("move", "cast") << '\n'
<< std::ranges::ends_with("move_if_noexcept", "cast") << '\n'
<< std::ranges::ends_with("forward", "cast") << '\n';
static_assert(
! std::ranges::ends_with("as_const", "cast") and
!! std::ranges::ends_with("bit_cast", "cast") and
! std::ranges::ends_with("to_underlying", "cast") and
!! std::ranges::ends_with(std::array {1,2,3,4}, std::array {3,4}) and
! std::ranges::ends_with(std::array {1,2,3,4}, std::array {4,5})
);
}
true
true
true
true
false
false
false
Hover to see the original license.