Namespaces
Variants

std::ranges:: find_last, std::ranges:: find_last_if, std::ranges:: find_last_if_not

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations (on sorted ranges)
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Permutation operations
Fold operations
Operations on uninitialized storage
Return types
Défini dans l'en-tête <algorithm>
Signature d'appel
(1)
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 = { } ) ;
(depuis C++23)
(jusqu'à 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 = { } ) ;
(depuis C++26)
(2)
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 = { } ) ;
(depuis C++23)
(jusqu'à 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 = { } ) ;
(depuis C++26)
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 = { } ) ;
(3) (depuis 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 = { } ) ;
(4) (depuis 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 = { } ) ;
(5) (depuis 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 = { } ) ;
(6) (depuis C++23)

Retourne le dernier élément de la plage [ first , last ) qui satisfait des critères spécifiques :

1) find_last recherche un élément égal à value .
3) find_last_if recherche le dernier élément dans l'intervalle [ first , last ) pour lequel le prédicat pred renvoie true .
5) find_last_if_not recherche le dernier élément dans la plage [ first , last ) pour lequel le prédicat pred retourne false .
2,4,6) Identique à (1,3,5) , mais utilise r comme plage source, comme si on utilisait ranges:: begin ( r ) comme first et ranges:: end ( r ) comme last .

Les entités de type fonction décrites sur cette page sont des objets fonction d'algorithme (informellement appelés niebloids ), c'est-à-dire :

Table des matières

Paramètres

first, last - la paire itérateur-sentinelle définissant la plage des éléments à examiner
r - la plage des éléments à examiner
value - valeur à comparer aux éléments
pred - prédicat à appliquer aux éléments projetés
proj - projection à appliquer aux éléments

Valeur de retour

1,3,5) Soit i le dernier itérateur dans l'intervalle [ first , last ) pour lequel E est true .
Retourne ranges:: subrange < I > { i, last } , ou ranges:: subrange < I > { last, last } si aucun itérateur de ce type n'est trouvé.
1) E est bool ( std:: invoke ( proj, * i ) == value ) .
3) E est bool ( std:: invoke ( pred, std:: invoke ( proj, * i ) ) ) .
5) E est bool ( ! std:: invoke ( pred, std:: invoke ( proj, * i ) ) ) .
2,4,6) Identique à (1,3,5) mais le type de retour est ranges:: borrowed_subrange_t < I > .

Complexité

Au plus last - first applications du prédicat et de la projection.

Notes

ranges::find_last , ranges::find_last_if , ranges::find_last_if_not offrent une meilleure efficacité sur les implémentations courantes si I modélise bidirectional_iterator ou (encore mieux) random_access_iterator .

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_lib_ranges_find_last 202207L (C++23) ranges::find_last ,
ranges::find_last_if ,
ranges::find_last_if_not
__cpp_lib_algorithm_default_value_type 202403L (C++26) Initialisation par liste pour les algorithmes ( 1,2 )

Implémentation possible

Ces implémentations montrent uniquement l'algorithme plus lent utilisé lorsque I modélise forward_iterator .

find_last (1,2)
struct find_last_fn
{
    template<std::forward_iterator I, std::sentinel_for<I> S,
             class Proj = std::identity,
             class T = std::projected_value_t<iterator_t<R>, Proj>>
    requires std::indirect_binary_predicate
                 <ranges::equal_to, std::projected<I, Proj>, const T*>
    constexpr ranges::subrange<I>
        operator()(I first, S last, const T &value, Proj proj = {}) const
    {
        // Remarque : si I est un simple forward_iterator, nous ne pouvons que parcourir du début à la fin.
        std::optional<I> found;
        for (; first != last; ++first)
            if (std::invoke(proj, *first) == value)
                found = first;
        if (!found)
            return {first, first};
        return {*found, std::ranges::next(*found, last)};
    }
    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>
        operator()(R&& r, const T &value, Proj proj = {}) const
    {
        return this->operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj));
    }
};
inline constexpr find_last_fn find_last;
find_last_if (3,4)
struct find_last_if_fn
{
    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>
        operator()(I first, S last, Pred pred, Proj proj = {}) const
    {
        // Remarque : si I est un simple forward_iterator, nous ne pouvons que parcourir du début à la fin.
        std::optional<I> found;
        for (; first != last; ++first)
            if (std::invoke(pred, std::invoke(proj, *first)))
                found = first;
        if (!found)
            return {first, first};
        return {*found, std::ranges::next(*found, last)};
    }
    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>
        operator()(R&& r, Pred pred, Proj proj = {}) const
    {
        return this->operator()(ranges::begin(r), ranges::end(r),
                                std::ref(pred), std::ref(proj));
    }
};
inline constexpr find_last_if_fn find_last_if;
find_last_if_not (5,6)
struct find_last_if_not_fn
{
    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>
        operator()(I first, S last, Pred pred, Proj proj = {}) const
    {
        // Note : si I est un simple forward_iterator, nous ne pouvons que parcourir du début à la fin.
        std::optional<I> found;
        for (; first != last; ++first)
            if (!std::invoke(pred, std::invoke(proj, *first)))
                found = first;
        if (!found)
            return {first, first};
        return {*found, std::ranges::next(*found, last)};
    }
    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>
        operator()(R&& r, Pred pred, Proj proj = {}) const
    {
        return this->operator()(ranges::begin(r), ranges::end(r),
                                std::ref(pred), std::ref(proj));
    }
};
inline constexpr find_last_if_not_fn find_last_if_not;

Exemple

#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
    {
        {"un", 1}, {"deux", 2}, {"trois", 3},
        {"un", 4}, {"deux", 5}, {"trois", 6},
    };
    auto cmp_one = [](const std::string_view &s) { return s == "un"; };
    // trouver le dernier élément qui satisfait le comparateur, en projetant pair::first
    const auto subrange = ranges::find_last_if(list, cmp_one, &P::premier);
    std::cout << "L'élément trouvé et la suite qui le suit sont :\n";
    for (P const& e : subrange)
        std::cout << '{' << std::quoted(e.premier) << ", " << e.second << "} ";
    std::cout << '\n';
#if __cpp_lib_algorithm_default_value_type
    const auto i3 = ranges::find_last(list, {"trois", 3}); // (2) C++26
#else
    const auto i3 = ranges::find_last(list, P{"trois", 3}); // (2) C++23
#endif
    assert(i3.begin()->first == "trois" && i3.begin()->second == 3);
}

Sortie :

L'élément trouvé et la suite après celui-ci sont :
{"one", 4} {"two", 5} {"three", 6}

Voir aussi

trouve la dernière séquence d'éléments dans une certaine plage
(objet fonction algorithme)
trouve le premier élément satisfaisant des critères spécifiques
(objet fonction algorithme)
recherche la première occurrence d'une plage d'éléments
(objet fonction algorithme)
retourne true si une séquence est une sous-séquence d'une autre
(objet fonction algorithme)
détermine si un élément existe dans une plage partiellement ordonnée
(objet fonction algorithme)
vérifie si la plage contient l'élément ou la sous-plage donnée
(objet fonction algorithme)