Spec-Zone.ru › C++

std::for_each

Определён в заголовочном файле <algorithm>
template< class InputIt, class UnaryFunc >
UnaryFunc for_each( InputIt first, InputIt last, UnaryFunc f );
(1) (constexpr since C++20)
template< class ExecutionPolicy, class ForwardIt, class UnaryFunc >
void for_each( ExecutionPolicy&& policy,
               ForwardIt first, ForwardIt last, UnaryFunc f );
(2) (since C++17)

Применяет заданный вызываемый объект f к каждому элементу целевого диапазона [first, last). Если f возвращает результат, этот результат игнорируется.

1) f применяется по порядку, начиная с first.

Если UnaryFunc не является MoveConstructible, поведение не определено.

(since C++11)
2) f может применяться не по порядку. Алгоритм выполняется согласно policy.
В отличие от других параллельных алгоритмов, for_each не может создавать произвольные копии элементов целевого диапазона.
Эта перегрузка участвует в разрешении перегрузки, только если значение следующего выражения равно true:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(until C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(since C++20)
Если UnaryFunc не является CopyConstructible, поведение не определено.

Параметры

first, last - пара итераторов, задающих целевой диапазон
f - функциональный объект, применяемый к элементам

Сигнатура функции должна быть эквивалентна следующей:

voidfun(constType&a);

Сигнатура не обязана содержать const &.
Тип Type должен быть таким, чтобы объект типа InputIt можно было разыменовать, а затем неявно преобразовать к Type.

​

policy - используемая политика выполнения
Требования к типам
-InputIt должен соответствовать требованиям LegacyInputIterator.
-ForwardIt должен соответствовать требованиям LegacyForwardIterator.

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

1) f

Сложность

Ровно std::distance(first, last) вызовов f.

Исключения

2) В процессе выполнения:
  • Если временные ресурсы памяти, необходимые для распараллеливания, недоступны, выбрасывается std::bad_alloc.
  • Если при обращении к объектам через аргумент алгоритма выбрасывается неперехваченное исключение, поведение определяется политикой выполнения (для стандартных политик вызывается std::terminate).

Примечания

Если тип итератора (InputIt/ForwardIt) является изменяемым, f может изменять элементы целевого диапазона.

Для перегрузки (1) f может быть функциональным объектом с состоянием. Возвращаемое значение можно рассматривать как конечное состояние пакетной операции.

Для перегрузки (2) для параллельного вызова может создаваться несколько копий f. Значение не возвращается, поскольку распараллеливание часто не позволяет эффективно накапливать состояние.

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

См. также реализации в 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; // implicit move since C++11
}

Пример

В следующем примере используется лямбда-выражение, чтобы увеличить все элементы вектора, а затем перегруженный operator() в вызываемом объекте — чтобы вычислить их сумму. Обратите внимание: для вычисления суммы рекомендуется использовать специализированный алгоритм 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 Применяется к Поведение согласно опубликованному стандарту Правильное поведение
LWG 475 C++98 было неясно, может ли f изменять элементы
последовательности, по которой выполняется итерация (for_each
классифицируется как «немодифицирующая операция над последовательностью»)
уточнено (разрешено, если
тип итератора является изменяемым)
LWG 2747 C++11 перегрузка (1) возвращала std::move(f) возвращает f (что выполняет неявное перемещение)

См. также

ranges::for_each
(C++20)
применяет унарный функциональный объект к элементам из диапазона
(функциональный объект алгоритма)
for_each_n
(C++17)
применяет функциональный объект к первым N элементам последовательности
(шаблон функции и функциональный объект алгоритма)
ranges::for_each_n
(C++20)
transform
применяет функцию к диапазону элементов, сохраняя результаты в целевом диапазоне
(шаблон функции и функциональный объект алгоритма)
ranges::transform
(C++20)
цикл range-for(C++11) выполняет цикл по диапазону

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

Spec-Zone.ru

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