Spec-Zone.ru › C++

std::ranges::find, std::ranges::find_if, std::ranges::find_if_not

Defined in header <algorithm>
Call signature
template< std::input_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 I
    find( I first, S last, const T& value, Proj proj = {} );
(1) (since C++20)
template< ranges::input_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_iterator_t<R>
    find( R&& r, const T& value, Proj proj = {} );
(2) (since C++20)
template< std::input_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
constexpr I
    find_if( I first, S last, Pred pred, Proj proj = {} );
(3) (since C++20)
template< ranges::input_range R, class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>,
                                        Proj>> Pred >
constexpr ranges::borrowed_iterator_t<R>
    find_if( R&& r, Pred pred, Proj proj = {} );
(4) (since C++20)
template< std::input_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
constexpr I
    find_if_not( I first, S last, Pred pred, Proj proj = {} );
(5) (since C++20)
template< ranges::input_range R, class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>,
                                        Proj>> Pred >
constexpr ranges::borrowed_iterator_t<R>
    find_if_not( R&& r, Pred pred, Proj proj = {} );
(6) (since C++20)

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

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

Функции, описанные на этой странице, являются niebloids, то есть:

  • Явные списки шаблонных аргументов не могут быть указаны при их вызове.
  • Они не видны для поиска зависимого от аргументов.
  • Когда любая из них обнаружена обычным поиском без квалификаторов в качестве имени слева от оператора вызова функции, поиск зависимый от аргументов заблокирован.

На практике они могут быть реализованы в виде объектов-функций или с помощью специальных расширений компилятора.

Параметры

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

Значение результата

Итератор на первый элемент, удовлетворяющий условию, или итератор, равный last, если такой элемент не найден.

Сложность

Максимум last - first применений предиката и проекции.

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

find
struct find_fn
{
    template<std::input_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 I operator()(I first, S last, const T& value, Proj proj = {}) const
    {
        for (; first != last; ++first)
            if (std::invoke(proj, *first) == value)
                return first;
        return first;
    }
 
    template<ranges::input_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_iterator_t<R>
        operator()(R&& r, const T& value, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), value, std::ref(proj));
    }
};
 
inline constexpr find_fn find;
find_if
struct find_if_fn
{
    template<std::input_iterator I, std::sentinel_for<I> S, class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
    constexpr I operator()(I first, S last, Pred pred, Proj proj = {}) const
    {
        for (; first != last; ++first)
            if (std::invoke(pred, std::invoke(proj, *first)))
                return first;
        return first;
    }
 
    template<ranges::input_range R, class Proj = std::identity,
             std::indirect_unary_predicate<
                 std::projected<ranges::iterator_t<R>, Proj>> Pred>
    constexpr ranges::borrowed_iterator_t<R>
        operator()(R&& r, Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
    }
};
 
inline constexpr find_if_fn find_if;
find_if_not
struct find_if_not_fn
{
    template<std::input_iterator I, std::sentinel_for<I> S, class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
    constexpr I operator()(I first, S last, Pred pred, Proj proj = {}) const
    {
        for (; first != last; ++first)
            if (!std::invoke(pred, std::invoke(proj, *first)))
                return first;
        return first;
    }
 
    template<ranges::input_range R, class Proj = std::identity,
             std::indirect_unary_predicate<
                 std::projected<ranges::iterator_t<R>, Proj>> Pred>
    constexpr ranges::borrowed_iterator_t<R>
        operator()(R&& r, Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
    }
};
 
inline constexpr find_if_not_fn find_if_not;

Пример

#include <algorithm>
#include <iostream>
#include <iterator>
 
int main()
{
    namespace ranges = std::ranges;
 
    const int n1 = 3;
    const int n2 = 5;
    const auto v = {4, 1, 3, 2};
 
    if (ranges::find(v, n1) != v.end())
        std::cout << "v contains: " << n1 << '\n';
    else
        std::cout << "v does not contain: " << n1 << '\n';
 
    if (ranges::find(v.begin(), v.end(), n2) != v.end())
        std::cout << "v contains: " << n2 << '\n';
    else
        std::cout << "v does not contain: " << n2 << '\n';
 
    auto is_even = [](int x) { return x % 2 == 0; };
 
    if (auto result = ranges::find_if(v.begin(), v.end(), is_even); result != v.end())
        std::cout << "First even element in v: " << *result << '\n';
    else
        std::cout << "No even elements in v\n";
 
    if (auto result = ranges::find_if_not(v, is_even); result != v.end())
        std::cout << "First odd element in v: " << *result << '\n';
    else
        std::cout << "No odd elements in v\n";
 
    auto divides_13 = [](int x) { return x % 13 == 0; };
 
    if (auto result = ranges::find_if(v, divides_13); result != v.end())
        std::cout << "First element divisible by 13 in v: " << *result << '\n';
    else
        std::cout << "No elements in v are divisible by 13\n";
 
    if (auto result = ranges::find_if_not(v.begin(), v.end(), divides_13);
        result != v.end())
        std::cout << "First element indivisible by 13 in v: " << *result << '\n';
    else
        std::cout << "All elements in v are divisible by 13\n";
}

Вывод:

v contains: 3
v does not contain: 5
First even element in v: 4
First odd element in v: 1
No elements in v are divisible by 13
First element indivisible by 13 in v: 4

См. также

ranges::adjacent_find
(C++20)
находит первые два смежных элемента, которые равны (или удовлетворяют заданному предикату)
(niebloid)
ranges::find_end
(C++20)
находит последнюю последовательность элементов в определенном диапазоне
(niebloid)
ranges::find_first_of
(C++20)
ищет любой из набора элементов
(niebloid)
ranges::mismatch
(C++20)
находит первую позицию, где два диапазона различаются
(niebloid)
ranges::search
(C++20)
ищет диапазон элементов
(niebloid)
findfind_iffind_if_not
(C++11)
находит первый элемент, удовлетворяющий определенным критериям
(шаблон функции)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/ranges/find

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API