std:: for_each
|
Определено в заголовке
<algorithm>
|
||
|
template
<
class
InputIt,
class
UnaryFunc
>
UnaryFunc for_each ( InputIt first, InputIt last, UnaryFunc f ) ; |
(1) | (constexpr начиная с C++20) |
|
template
<
class
ExecutionPolicy,
class
ForwardIt,
class
UnaryFunc
>
void
for_each
(
ExecutionPolicy
&&
policy,
|
(2) | (начиная с C++17) |
Применяет заданный унарный
функциональный объект
f
к результату разыменования каждого
итератора
в
диапазоне
[
first
,
last
)
. Если
f
возвращает результат, он игнорируется.
|
Если
|
(начиная с C++11) |
|
std:: is_execution_policy_v < std:: decay_t < ExecutionPolicy >> равно true . |
(до C++20) |
|
std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> равно true . |
(начиная с C++20) |
Если тип итератора (
InputIt
/
ForwardIt
) является изменяемым,
f
может модифицировать элементы
диапазона
через разыменованный итератор.
В отличие от остальных параллельных алгоритмов,
for_each
не разрешается создавать копии элементов в последовательности, даже если они являются
TriviallyCopyable
.
Содержание |
Параметры
| first, last | - | пара итераторов, определяющих диапазон элементов, к которым будет применён функциональный объект |
| policy | - | политика выполнения, которая будет использована |
| f | - |
функциональный объект, который будет применён к результату разыменования каждого итератора в
диапазоне
[
first
,
last
)
Сигнатура функции должна быть эквивалентна следующей: void fun ( const Type & a ) ;
Сигнатура не обязана иметь
const
&
.
|
| Требования к типам | ||
-
InputIt
должен удовлетворять требованиям
LegacyInputIterator
.
|
||
-
ForwardIt
должен удовлетворять требованиям
LegacyForwardIterator
.
|
||
Возвращаемое значение
Сложность
Ровно std:: distance ( first, last ) применений функции f .
Исключения
Перегрузка с параметром шаблона с именем
ExecutionPolicy
сообщает об ошибках следующим образом:
-
Если выполнение функции, вызванной как часть алгоритма, выбрасывает исключение и
ExecutionPolicyявляется одним из стандартных политик , std::terminate вызывается. Для любой другойExecutionPolicyповедение определяется реализацией. - Если алгоритму не удается выделить память, std::bad_alloc выбрасывается.
Возможная реализация
Смотрите также реализации в libstdc++ , libc++ и MSVC stdlib .
template<class InputIt, class UnaryFunc> constexpr UnaryFunc for_each(InputIt first, InputIt last, UnaryFunc f) { for (; first != last; ++first) f(*first); return f; // неявное перемещение начиная с C++11 } |
Примечания
Для перегрузки ( 1 ) , f может быть функциональным объектом с состоянием. Возвращаемое значение может рассматриваться как конечное состояние пакетной операции.
Для перегрузки ( 2 ) может быть создано несколько копий f для выполнения параллельного вызова. Значение не возвращается, поскольку параллелизация часто не позволяет эффективно накапливать состояние.
Пример
Следующий пример использует
lambda-expression
для инкремента всех элементов вектора, а затем использует перегруженный
operator()
в функциональном объекте (также известном как "functor") для вычисления их суммы. Обратите внимание, что для вычисления суммы рекомендуется использовать специализированный алгоритм
std::accumulate
.
#include <algorithm> #include <iostream> #include <vector> int main() { std::vector<int> v{3, -4, 2, -8, 15, 267}; auto print = [](const int& n) { std::cout << n << ' '; }; std::cout << "before:\t"; std::for_each(v.cbegin(), v.cend(), print); std::cout << '\n'; // increment elements in-place std::for_each(v.begin(), v.end(), [](int &n) { n++; }); std::cout << "after:\t"; std::for_each(v.cbegin(), v.cend(), print); std::cout << '\n'; struct Sum { void operator()(int n) { sum += n; } int sum {0}; }; // invoke Sum::operator() for each element Sum s = std::for_each(v.cbegin(), v.cend(), Sum()); std::cout << "sum:\t" << s.sum << '\n'; }
Вывод:
before: 3 -4 2 -8 15 267 after: 4 -3 3 -7 16 268 sum: 281
Отчёты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 475 | C++98 |
было неясно, может ли
f
изменять элементы
последовательности, по которой выполняется итерация (
for_each
классифицируется
как "немодифицирующие операции с последовательностями") |
прояснено (разрешено, если тип
итератора является изменяемым) |
| LWG 2747 | C++11 | перегрузка ( 1 ) возвращала std :: move ( f ) | возвращает f (что неявно выполняет перемещение) |
Смотрите также
|
применяет функцию к диапазону элементов, сохраняя результаты в целевом диапазоне
(шаблон функции) |
|
|
(C++17)
|
применяет функциональный объект к первым N элементам последовательности
(шаблон функции) |
|
(C++20)
|
применяет унарный
функциональный объект
к элементам из
диапазона
(функциональный объект алгоритма) |
|
(C++20)
|
применяет функциональный объект к первым N элементам последовательности
(функциональный объект алгоритма) |
цикл по диапазону
for
(C++11)
|
выполняет цикл по диапазону |