namespace std::ranges {
template <input_iterator I,
class Proj = identity,
indirectly_unary_invocable<projected<I, Proj>> Fun>
constexpr for_each_n_result<I, Fun>
for_each_n(I first,
iter_difference_t<I> n,
Fun f,
Proj proj = {}); // (1) C++20
template <execution-policy Ep,
random_access_iterator I,
class Proj = identity,
indirectly_unary_invocable<projected<I, Proj>> Fun>
I for_each_n(Ep&& exec,
I first,
iter_difference_t<I> n,
Fun f,
Proj proj = {}); // (2) C++26
}
概要
範囲の先頭N個の要素に、指定された関数を適用する。
- (1): 通常版
- (2): 並列アルゴリズム版。実行ポリシーを指定する
テンプレートパラメータ制約
Iがinput_iteratorであるFunはIをProjで射影した値を受け取る1引数のinvocableである
この他にFunはcopy_constructibleのモデルであることが要求される。
事前条件
n >= 0
効果
イテレータ範囲[first, first + n) 内の全てのイテレータ i に invoke(f, invoke(proj, *i)) という操作を行う。
このアルゴリズムはその他のアルゴリズムと違い、invoke(proj, *i) が書き換え可能な参照であれば、関数 f の内部でその値を書き換えても構わない。
戻り値
-
(1):
for_each_n_result { .in = first + n, .fun = std::move(f) } -
(2):
first + n
備考
- 関数
fに戻り値がある場合、それは単に無視される
例
基本的な使い方
#include <iostream>
#include <algorithm>
#include <array>
void f(int& x)
{
x *= 2;
}
int main()
{
std::array v = {3, 1, 4, 5, 2};
// コンテナvの先頭3要素に、関数f()を適用する。
// 関数f()は要素の変更を行う
std::ranges::for_each_n(v.begin(), 3, f);
// コンテナvの先頭3要素に、ラムダ式で記述した関数オブジェクトを適用する
std::ranges::for_each_n(v.begin(), 3, [](int x) {
std::cout << x << std::endl;
});
}
出力
6
2
8
並列アルゴリズムの例 (C++26)
#include <algorithm>
#include <execution>
#include <iostream>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
// 並列に先頭3要素を出力
std::ranges::for_each_n(std::execution::par, v.begin(), 3,
[](int x) { std::cout << x << ' '; });
std::cout << std::endl;
}
出力例
1 2 3
バージョン
言語
- C++20
処理系
- Clang: ??
- GCC: 10.1.0 ✅
- ICC: ??
- Visual C++: 2019 Update 10 ✅
実装例
struct for_each_n_impl {
template<input_iterator I, class Proj = identity, indirectly_unary_invocable<projected<I, Proj>> Fun>
requires copy_constructible<Fun>
constexpr for_each_n_result<I, Fun> operator()(I first, iter_difference_t<I> n, Fun f, Proj proj = {}) const {
for (iter_difference_t<I> i = 0; i < n; ++i) {
invoke(f, invoke(proj, *first));
++first;
}
return {move(first), move(f)};
}
};
inline constexpr for_each_n_impl for_each_n;