Spec-Zone.ru › C++

std::for_each

Defined in header <algorithm>
(1)
template< class InputIt, class UnaryFunction >
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );
(до C++20)
template< class InputIt, class UnaryFunction >
constexpr UnaryFunction for_each( InputIt first, InputIt last,
                                  UnaryFunction f );
(с C++20)
template< class ExecutionPolicy, class ForwardIt, class UnaryFunction2 >
void for_each( ExecutionPolicy&& policy,
               ForwardIt first, ForwardIt last, UnaryFunction2 f );
(2) (с C++17)
1) Применяет заданный объект функции f к результату обращений к каждому итератору в диапазоне [first, last), в порядке следования.
2) Применяет заданный объект функции f к результату обращений к каждому итератору в диапазоне [first, last) (не обязательно в порядке следования). Алгоритм выполняется согласно policy. Этот перегруз не участвует в разрешении перегрузки, если

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 может изменить элементы диапазона через обращение к итератору. Если f возвращает результат, результат игнорируется.

В отличие от остальных параллельных алгоритмов, for_each не допускается копировать элементы в последовательности, даже если они являются TriviallyCopyable.

Параметры

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

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

void fun(const Type &a);

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

​

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

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

1)

f

(до C++11)

std::move(f)

(с C++11)
2) (ничего)

Сложность

Точно std::distance(first, last) приложений f.

Исключения

Перегрузка с параметром шаблона, названным ExecutionPolicy сообщает об ошибках следующим образом:

  • Если выполнение функции, вызванной как часть алгоритма, вызывает исключение, и ExecutionPolicy является одной из стандартных политик, std::terminate вызывается. Для любой другой ExecutionPolicy, поведение является определенным реализацией.
  • Если алгоритм не может выделить память, std::bad_alloc выбрасывается.

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

См. также реализации в libstdc++, libc++ и MSVC stdlib.

template<class InputIt, class UnaryFunction>
constexpr UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
{
    for (; first != last; ++first)
        f(*first);
 
    return f; // implicit move since C++11
}

Пример

В следующем примере используется lambda-выражение для увеличения всех элементов вектора, а затем используется перегруженная 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 классифицируется как «операции над последовательностями без изменения»)
определено (разрешено, если тип итератора изменяемый)

См. также

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

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

Spec-Zone.ru

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