std::ranges::find_first_of
Определено в заголовочном файле <algorithm> | ||
|---|---|---|
| Подпись вызова функции | ||
template< std::input_iterator I1, std::sentinel_for<I1> S1,
std::forward_iterator I2, std::sentinel_for<I2> S2,
class Pred = ranges::equal_to,
class Proj1 = std::identity,
class Proj2 = std::identity >
requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
constexpr I1 find_first_of( I1 first1, S1 last1, I2 first2, S2 last2,
Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );
| (1) | (с C++20) |
template< ranges::input_range R1, ranges::forward_range R2,
class Pred = ranges::equal_to,
class Proj1 = std::identity,
class Proj2 = std::identity >
requires std::indirectly_comparable<ranges::iterator_t<R1>,
ranges::iterator_t<R2>,
Pred, Proj1, Proj2>
constexpr ranges::borrowed_iterator_t<R1>
find_first_of( R1&& r1, R2&& r2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {} );
| (2) | (с C++20) |
[first1, last1) любой из элементов в диапазоне [first2, last2), после применения проекций к диапазонам с использованием proj1 и proj2 соответственно. Проектированные элементы сравниваются с помощью бинарного предиката pred. r1 в качестве первого исходного диапазона и r2 в качестве второго исходного диапазона, как если бы использовались ranges::begin(r1) как first1, ranges::end(r1) как last1, ranges::begin(r2) как first2, и ranges::end(r2) как last2. Функциональные сущности, описанные на этой странице, являются неблоидами, то есть:
- Нельзя указать явные списки шаблонных аргументов при их вызове.
- Они не видны для поиска аргументов, зависящих от контекста (ADL).
- Если один из них найден обычным поиском без указания имени (неквалифицированный поиск) как имя слева от оператора вызова функции, поиск аргументов, зависящих от контекста (ADL), запрещён.
На практике их можно реализовать как объекты-функции или с помощью специальных расширений компилятора.
Параметры
| first1, last1 | - | диапазон элементов для проверки (также известный как искомое множество) |
| first2, last2 | - | диапазон элементов для поиска (также известный как образцы) |
| r1 | - | диапазон элементов для проверки (также известный как искомое множество) |
| r2 | - | диапазон элементов для поиска (также известный как образцы) |
| pred | - | бинарный предикат для сравнения элементов |
| proj1 | - | проекция, применяемая к элементам в первом диапазоне |
| proj2 | - | проекция, применяемая к элементам во втором диапазоне |
Возвращаемое значение
Итератор на первый элемент в диапазоне [first1, last1) , который равен элементу из диапазона [first2, last2) после применения проекций. Если такой элемент не найден, возвращается итератор, сравниваемый с last1.
Сложность
Максимально S * N применений предиката и каждой проекции, где
(1) S = ranges::distance(first2, last2) и N = ranges::distance(first1, last1);
(2) S = ranges::distance(r2) и N = ranges::distance(r1).
Возможная реализация
struct find_first_of_fn
{
template<std::input_iterator I1, std::sentinel_for<I1> S1,
std::forward_iterator I2, std::sentinel_for<I2> S2,
class Pred = ranges::equal_to,
class Proj1 = std::identity,
class Proj2 = std::identity>
requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
constexpr I1 operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
for (; first1 != last1; ++first1)
for (auto i = first2; i != last2; ++i)
if (std::invoke(pred, std::invoke(proj1, *first1), std::invoke(proj2, *i)))
return first1;
return first1;
}
template<ranges::input_range R1, ranges::forward_range R2,
class Pred = ranges::equal_to,
class Proj1 = std::identity,
class Proj2 = std::identity>
requires std::indirectly_comparable<ranges::iterator_t<R1>,
ranges::iterator_t<R2>,
Pred, Proj1, Proj2>
constexpr ranges::borrowed_iterator_t<R1>
operator()(R1&& r1, R2&& r2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
return (*this)(ranges::begin(r1), ranges::end(r1),
ranges::begin(r2), ranges::end(r2),
std::move(pred), std::move(proj1), std::move(proj2));
}
};
inline constexpr find_first_of_fn find_first_of {}; |
Пример
#include <algorithm>
#include <iostream>
#include <iterator>
int main()
{
namespace rng = std::ranges;
constexpr static auto haystack = {1, 2, 3, 4};
constexpr static auto needles = {0, 3, 4, 3};
constexpr auto found1 = rng::find_first_of(haystack.begin(), haystack.end(),
needles.begin(), needles.end());
static_assert(std::distance(haystack.begin(), found1) == 2);
constexpr auto found2 = rng::find_first_of(haystack, needles);
static_assert(std::distance(haystack.begin(), found2) == 2);
constexpr static auto negatives = {-6, -3, -4, -3};
constexpr auto not_found = rng::find_first_of(haystack, negatives);
static_assert(not_found == haystack.end());
constexpr auto found3 = rng::find_first_of(haystack, negatives,
[](int x, int y) { return x == -y; }); // uses a binary comparator
static_assert(std::distance(haystack.begin(), found3) == 2);
struct P { int x, y; };
constexpr static auto p1 = {P{1, -1}, P{2, -2}, P{3, -3}, P{4, -4}};
constexpr static auto p2 = {P{5, -5}, P{6, -3}, P{7, -5}, P{8, -3}};
// Compare only P::y data members by projecting them:
const auto found4 = rng::find_first_of(p1, p2, {}, &P::y, &P::y);
std::cout << "First equivalent element {" << found4->x << ", " << found4->y
<< "} was found at position " << std::distance(p1.begin(), found4)
<< ".\n";
}Вывод:
First equivalent element {3, -3} was found at position 2.См. также
| поиск любого из набора элементов (шаблон функции) |
|
|
(C++20) | находит первые два смежных элемента, которые равны (или удовлетворяют заданному предикату) (неблоид) |
|
(C++20)(C++20)(C++20) | находит первый элемент, удовлетворяющий определённым критериям (неблоид) |
|
(C++20) | находит последнее последовательность элементов в определённом диапазоне (неблоид) |
|
(C++20) | выполняет поиск диапазона элементов (неблоид) |
|
(C++20) | выполняет поиск заданного числа последовательных копий элемента в диапазоне (неблоид) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/ranges/find_first_of