std::for_each(3)
β¨ NAME β¨
std::for_each β literally just std::for_each, bestie. No cap, that's the whole name. It's giving "what it says on the tin."
πΈ SYNOPSIS πΈ
Defined in header <algorithm>:
template< class InputIt, class UnaryFunc >
UnaryFunc for_each( InputIt first, InputIt last, (1)
(constexpr since C++20)
UnaryFunc f );
template< class ExecutionPolicy, class ForwardIt, class UnaryFunc >
void for_each( ExecutionPolicy&& policy, (2) (since C++17)
ForwardIt first, ForwardIt last,
UnaryFunc f );
Okay so real talk: this algorithm applies the given function object f to the result of dereferencing every iterator in the range [first, last). If f returns a result, the result is ignored. Like, we don't care about your return value here, bestie. It's giving "do the thing and move on."
1) f is applied in order starting from first.
If UnaryFunc is not MoveConstructible, the behavior is undefined. (since C++11)
2) f might not be applied in order. The algorithm is executed according to policy.
This overload participates in overload resolution only if:
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>istrue. (until C++20)std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>istrue. (since C++20)
If UnaryFunc is not CopyConstructible, the behavior is undefined.
If the iterator type (InputIt/ForwardIt) is mutable, f may modify the elements of the range through the dereferenced iterator.
Important vibe check: Unlike the rest of the parallel algorithms, for_each is not allowed to make copies of the elements in the sequence even if they are TriviallyCopyable. Periodt. That's just how it is.
π PARAMETERS π
first,lastβ the range to apply the function to. Like, the whole squad of elements you're about to hit withf.policyβ the execution policy to use. See execution policy for details. (iykyk)fβ function object, to be applied to the result of dereferencing every iterator in the range[first, last). The signature of the function should be equivalent to the following:
void fun(const Type &a);
The signature does not need to have const &. The type Type must be such that an object of type InputIt can be dereferenced and then implicitly converted to Type.
π¦ TYPE REQUIREMENTS π¦
InputItmust meet the requirements of LegacyInputIterator.ForwardItmust meet the requirements of LegacyForwardIterator.
π RETURN VALUE π
fβ yes, it returns your function object back to you. Like, "here bestie, you dropped this."- (none) β for the parallel overload, it's giving "nothing to see here."
β COMPLEXITY β
Exactly std::distance(first, last) applications of f. No more, no less. It's giving "precise queen."
π₯ EXCEPTIONS π₯
The overload with a template parameter named ExecutionPolicy reports errors as follows:
- If execution of a function invoked as part of the algorithm throws an exception and
ExecutionPolicyis one of the standard policies,std::terminateis called. For any otherExecutionPolicy, the behavior is implementation-defined. - If the algorithm fails to allocate memory,
std::bad_allocis thrown.
Warning bestie: std::terminate is not a vibe. It literally kills your program. So like, don't let your function throw with standard policies, okay? π«Ά
π POSSIBLE IMPLEMENTATION π
See also the implementations in libstdc++, libc++ and 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
}
Like, that's it. That's the whole algorithm. So simple, so iconic.
π NOTES π
For overload (1), f can be a stateful function object. The return value can be considered as the final state of the batch operation. Like, you can accumulate state in your functor and get it back at the end. Main character energy.
For overload (2), multiple copies of f may be created to perform parallel invocation. No value is returned because parallelization often does not permit efficient state accumulation. It's giving "we tried but the vibes were off."
π EXAMPLE π
The following example uses a lambda-expression to increment all of the elements of a vector and then uses an overloaded operator() in a function object (a.k.a., "functor") to compute their sum. Note that to compute the sum, it is recommended to use the dedicated algorithm std::accumulate.
// Run this code
#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';
}
Output:
before: 3 -4 2 -8 15 267
after: 4 -3 3 -7 16 268
sum: 281
π§ DEFECT REPORTS π§
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
- LWG 475 β Applied to: C++98. Behavior as published: it was unclear whether
fcan modify the elements of the sequence being iterated over (for_eachis classified as "non-modifying sequence operations"). Correct behavior: made clear (allowed if the iterator type is mutable). - LWG 2747 β Applied to: C++11. Behavior as published: overload (1) returned
std::move(f). Correct behavior: returnsf(which implicitly moves).
Like, they really said "let's clarify this" and we love that for us. π
π SEE ALSO π
transformβ applies a function to a range of elements, storing results in a destination range. (function template)for_each_n(C++17) β applies a function object to the first N elements of a sequence. (function template)ranges::for_each(C++20) β applies a function to a range of elements. (niebloid)ranges::for_each_n(C++20) β applies a function object to the first N elements of a sequence. (niebloid)range-for loop(C++11) β executes loop over range.
So yeah, that's std::for_each. Go forth and apply functions to your ranges, bestie. You got this. π
β¨
This iconic piece of documentation was brought to you by http://cppreference.com, dated 2024.06.10, and the manual page is literally std::for_each(3). Slay. π
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms