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
Определено в заголовке <algorithm>
Сигнатура вызова
(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 = { } ) ;
(начиная с C++23)
(до 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 = { } ) ;
(начиная с 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 = { } ) ;
(начиная с C++23)
(до 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 = { } ) ;
(начиная с 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) (начиная с 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) (начиная с 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) (начиная с 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) (начиная с C++23)

Возвращает последний элемент в диапазоне [ first , last ) удовлетворяющий определённым критериям:

1) find_last ищет элемент, равный value .
3) find_last_if ищет последний элемент в диапазоне [ first , last ) для которого предикат pred возвращает true .
5) find_last_if_not ищет последний элемент в диапазоне [ first , last ) для которого предикат pred возвращает false .
2,4,6) То же, что (1,3,5) , но использует r в качестве исходного диапазона, как если бы использовались ranges:: begin ( r ) в качестве first и ranges:: end ( r ) в качестве last .

Функциональные сущности, описанные на этой странице, являются алгоритмическими функциональными объектами (неформально известными как niebloids ), то есть:

  • Явные списки аргументов шаблона не могут быть указаны при вызове любого из них.
  • Ни один из них не видим для argument-dependent lookup .
  • Когда любой из них найден с помощью normal unqualified lookup как имя слева от оператора вызова функции, argument-dependent lookup блокируется.

Содержание

Параметры

first, last - пара итератор-страж, определяющая диапазон элементов для проверки
r - диапазон элементов для проверки
value - значение для сравнения с элементами
pred - предикат для применения к проецируемым элементам
proj - проекция для применения к элементам

Возвращаемое значение

1,3,5) Пусть i будет последним итератором в диапазоне [ first , last ) для которого E является true .
Возвращает ranges:: subrange < I > { i, last } , или ranges:: subrange < I > { last, last } если такой итератор не найден.
1) E является bool ( std:: invoke ( proj, * i ) == value ) .
3) E является bool ( std:: invoke ( pred, std:: invoke ( proj, * i ) ) ) .
5) E является bool ( ! std:: invoke ( pred, std:: invoke ( proj, * i ) ) ) .
2,4,6) То же, что (1,3,5) , но возвращаемый тип — ranges:: borrowed_subrange_t < I > .

Сложность

Не более last - first применений предиката и проекции.

Примечания

ranges::find_last , ranges::find_last_if , ranges::find_last_if_not обладают лучшей эффективностью в распространённых реализациях, если I моделирует bidirectional_iterator или (предпочтительно) random_access_iterator .

Макрос тестирования возможностей Значение Стандарт Функция
__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) Списковая инициализация для алгоритмов ( 1,2 )

Возможная реализация

Эти реализации показывают только более медленный алгоритм, используемый, когда I моделирует forward_iterator .

Перевод: Примечания: - HTML-теги и атрибуты сохранены без изменений - Термин "find_last" не переведен, так как это C++ специфичный термин - Числовые значения в скобках сохранены - Форматирование и структура HTML полностью сохранены **Перевод:** **Примечания:** - HTML-теги и атрибуты сохранены без изменений - Функция `find_last_if_not` переведена как `найти_последний_если_не` в соответствии с принятой терминологией для алгоритмов C++ - Номера версий (5,6) оставлены без перевода - Форматирование и структура HTML полностью сохранены
find_last (1,2)
найти_последний (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
    {
        // Примечание: если I является простым forward_iterator, мы можем пройти только от начала до конца.
        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
    {
        // Примечание: если I является простым forward_iterator, мы можем пройти только от начала до конца.
        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)
найти_последний_если_не (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
    {
        // Примечание: если I является простым forward_iterator, мы можем пройти только от начала до конца.
        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;

Пример

#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
    {
        {"один", 1}, {"два", 2}, {"три", 3},
        {"один", 4}, {"два", 5}, {"три", 6},
    };
    auto cmp_one = [](const std::string_view &s) { return s == "один"; };
    // найти последний элемент, удовлетворяющий компаратору, с проекцией pair::first
    const auto subrange = ranges::find_last_if(list, cmp_one, &P::первый);
    std::cout << "Найденный элемент и хвост после него:\n";
    for (P const& e : subrange)
        std::cout << '{' << std::quoted(e.первый) << ", " << e.second << "} ";
    std::cout << '\n';
#if __cpp_lib_algorithm_default_value_type
    const auto i3 = ranges::find_last(list, {"три", 3}); // (2) C++26
#else
    const auto i3 = ranges::find_last(list, P{"три", 3}); // (2) C++23
#endif
    assert(i3.begin()->first == "три" && i3.begin()->second == 3);
}

Вывод:

Найденный элемент и хвост после него:
{"one", 4} {"two", 5} {"three", 6}

Смотрите также

находит последнюю последовательность элементов в заданном диапазоне
(функциональный объект алгоритма)
находит первый элемент, удовлетворяющий определенным критериям
(функциональный объект алгоритма)
ищет первое вхождение диапазона элементов
(функциональный объект алгоритма)
возвращает true если одна последовательность является подпоследовательностью другой
(функциональный объект алгоритма)
определяет, существует ли элемент в частично упорядоченном диапазоне
(функциональный объект алгоритма)
проверяет, содержит ли диапазон заданный элемент или поддиапазон
(функциональный объект алгоритма)