std::ranges...last_if_not(3)
π std::ranges...last_if_not(3) β C++ Standard Library π
manual page:std::ranges...last_if_not(3)from theC++ Standard Libarysection (their spelling, not mine π), bestie.
πΈ NAME πΈ
okay so this page is serving std::ranges::find_last, std::ranges::find_last_if, and std::ranges::find_last_if_not β the last-element-hunting trio. The truncated-looking manual title is just the header vibe; the real names are:
std::ranges::find_laststd::ranges::find_last_ifstd::ranges::find_last_if_not
β¨ Synopsis β¨
Defined in header <algorithm>
π Call signature π
(1) find_last β iterator flavor
(since C++23) (until C++26)
template< std::forward_iterator I, std::sentinel_for<I> S,
class T,
class Proj = std::identity >
requires std::indirect_binary_predicate<ranges::equal_to,
std::projected<I, Proj>,
const T*>
constexpr ranges::subrange<I>
find_last( I first, S last, const T& value, Proj proj = {} );
(since C++26)
template< std::forward_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
class T = std::projected_value_t<I, Proj> >
requires std::indirect_binary_predicate<ranges::equal_to,
std::projected<I, Proj>,
const T*>
constexpr ranges::subrange<I>
find_last( I first, S last, const T& value, Proj proj = {} );
(2) find_last β range flavor
(since C++23) (until C++26)
template< ranges::forward_range R,
class T,
class Proj = std::identity >
requires std::indirect_binary_predicate<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>,
const T*>
constexpr ranges::borrowed_subrange_t<R>
find_last( R&& r, const T& value, Proj proj = {} );
(since C++26)
template< ranges::forward_range R,
class Proj = std::identity,
class T = std::projected_value_t<iterator_t<R>, Proj> >
requires std::indirect_binary_predicate<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>,
const T*>
constexpr ranges::borrowed_subrange_t<R>
find_last( R&& r, const T& value, Proj proj = {} );
(3) find_last_if β iterator flavor
(since C++23)
template< std::forward_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>>
Pred >
constexpr ranges::subrange<I>
find_last_if( I first, S last, Pred pred, Proj proj = {} );
(4) find_last_if β range flavor
(since C++23)
template< ranges::forward_range R, class Proj = std::identity,
std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>,
Proj>>
Pred >
constexpr ranges::borrowed_subrange_t<R>
find_last_if( R&& r, Pred pred, Proj proj = {} );
(5) find_last_if_not β iterator flavor
(since C++23)
template< std::forward_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>>
Pred >
constexpr ranges::subrange<I>
find_last_if_not( I first, S last, Pred pred, Proj proj = {} );
(6) find_last_if_not β range flavor
(since C++23)
template< ranges::forward_range R, class Proj = std::identity,
std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>,
Proj>>
Pred >
constexpr ranges::borrowed_subrange_t<R>
find_last_if_not( R&& r, Pred pred, Proj proj = {} );
Returns the last element in the range [first, last) that satisfies specific criteria:
1)find_lastsearches for an element equal tovalue.3)find_last_ifsearches for the last element in the range[first, last)for which predicatepredreturns true.5)find_last_if_notsearches for the last element in the range[first, last)for which predicatepredreturns false.2,4,6)Same as(1,3,5), but usesras the source range, as if usingranges::begin(r)asfirstandranges::end(r)aslast.
The function-like entities described on this page are niebloids, that is:
- Explicit template argument lists cannot be specified when calling any of them.
- None of them are visible to argument-dependent lookup.
- When any of them are found by normal unqualified lookup as the name to the left of the function-call operator, argument-dependent lookup is inhibited.
In practice, they may be implemented as function objects, or with special compiler extensions.
π¦ Parameters π¦
first, lastβ the range of elements to examinerβ the range of the elements to examinevalueβ value to compare the elements topredβ predicate to apply to the projected elementsprojβ projection to apply to the elements
π₯ Return value π₯
1,2,3)Letibe the last iterator in the range[first, last)for whichEis true. Returnsranges::subrange<I>{i, last}, orranges::subrange<I>{last, last}if no such iterator is found.2,4,6)Same as(1,2,3)but the return type isranges::borrowed_subrange_t<I>.
π Complexity π
At most last - first applications of the predicate and projection.
π Notes π
ranges::find_last, ranges::find_last_if, ranges::find_last_if_not have better efficiency on common implementations if I models bidirectional_iterator or (better) random_access_iterator.
Feature-test macro vibes:
__cpp_lib_ranges_find_lastβ value202207L, std(C++23), featureranges::find_last, ranges::find_last_if, ranges::find_last_if_not__cpp_lib_algorithm_default_value_typeβ value202403, std(C++26), feature List-initialization for algorithms(1,2)
βοΈ part 2 has thePossible implementationcode blocks β the slowerforward_iteratorpath is about to have its main character moment, bestie π
β¨ EXAMPLE β¨
okay bestie, this is the part where we actually run the thing π€π here's the full code β copy it, compile it, and watch it do its little dance:
// Run this code
#include <algorithm>
#include <cassert>
#include <forward_list>
#include <iomanip>
#include <iostream>
#include <string_view>
int main()
{
namespace ranges = std::ranges;
constexpr static auto v = {1, 2, 3, 1, 2, 3, 1, 2};
{
constexpr auto i1 = ranges::find_last(v.begin(), v.end(), 3);
constexpr auto i2 = ranges::find_last(v, 3);
static_assert(ranges::distance(v.begin(), i1.begin()) == 5);
static_assert(ranges::distance(v.begin(), i2.begin()) == 5);
}
{
constexpr auto i1 = ranges::find_last(v.begin(), v.end(), -3);
constexpr auto i2 = ranges::find_last(v, -3);
static_assert(i1.begin() == v.end());
static_assert(i2.begin() == v.end());
}
auto abs = [](int x) { return x < 0 ? -x : x; };
{
auto pred = [](int x) { return x == 3; };
constexpr auto i1 = ranges::find_last_if(v.begin(), v.end(), pred, abs);
constexpr auto i2 = ranges::find_last_if(v, pred, abs);
static_assert(ranges::distance(v.begin(), i1.begin()) == 5);
static_assert(ranges::distance(v.begin(), i2.begin()) == 5);
}
{
auto pred = [](int x) { return x == -3; };
constexpr auto i1 = ranges::find_last_if(v.begin(), v.end(), pred, abs);
constexpr auto i2 = ranges::find_last_if(v, pred, abs);
static_assert(i1.begin() == v.end());
static_assert(i2.begin() == v.end());
}
{
auto pred = [](int x) { return x == 1 or x == 2; };
constexpr auto i1 = ranges::find_last_if_not(v.begin(), v.end(), pred, abs);
constexpr auto i2 = ranges::find_last_if_not(v, pred, abs);
static_assert(ranges::distance(v.begin(), i1.begin()) == 5);
static_assert(ranges::distance(v.begin(), i2.begin()) == 5);
}
{
auto pred = [](int x) { return x == 1 or x == 2 or x == 3; };
constexpr auto i1 = ranges::find_last_if_not(v.begin(), v.end(), pred, abs);
constexpr auto i2 = ranges::find_last_if_not(v, pred, abs);
static_assert(i1.begin() == v.end());
static_assert(i2.begin() == v.end());
}
using P = std::pair<std::string_view, int>;
std::forward_list<P> list
{
{"one", 1}, {"two", 2}, {"three", 3},
{"one", 4}, {"two", 5}, {"three", 6},
};
auto cmp_one = [](const std::string_view &s) { return s == "one"; };
// find latest element that satisfy the comparator, and projecting pair::first
const auto subrange = ranges::find_last_if(list, cmp_one, &P::first);
// print the found element and the "tail" after it
for (P const& e : subrange)
std::cout << '{' << std::quoted(e.first) << ", " << e.second << "} ";
std::cout << '\n';
#if __cpp_lib_algorithm_default_value_type
const auto i3 = ranges::find_last(list, {"three", 3}); // (2) C++26
#else
const auto i3 = ranges::find_last(list, P{"three", 3}); // (2) C++23
#endif
assert(i3.begin()->first == "three" && i3.begin()->second == 3);
}
and the output is literally this adorable little line:
{"one", 4} {"two", 5} {"three", 6}
bestie, if you see that output, you ate and left no crumbs π π₯
π SEE ALSO π
like, if you're obsessed with this function (same), here are its besties:
ranges::find_endβ finds the last sequence of elements in a certain range. (C++20) (niebloid)ranges::find,ranges::find_if,ranges::find_if_notβ finds the first element satisfying specific criteria. (C++20) (niebloid) for eachranges::searchβ searches for a range of elements. (C++20) (niebloid)ranges::includesβ returns true if one sequence is a subsequence of another. (C++20) (niebloid)ranges::binary_searchβ determines if an element exists in a partially-ordered range. (C++20) (niebloid)ranges::contains,ranges::contains_subrangeβ checks if the range contains the given element or subrange. (C++23) (niebloid) for each
that's the whole vibe β¨ page source is cppreference.com, version 2024.06.10, and the page is std::ranges...last_if_not(3). now go be the main character of your own algorithm era π«Άπ
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms