最終更新日時: 2026年02月05日 13時53分18秒 (JST)
Akira Takahashi が更新

履歴 編集

function template
<algorithm>

# std::ranges::for_each_n(C++20)

    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;

## 参照

- N4861 25 Algorithms library
- P3179R9 C++ parallel range algorithms