最終更新日時(UTC):
が更新

履歴 編集

function template
<algorithm>

std::for_each

namespace std {
  template <class InputIterator, class Function>
  Function for_each(InputIterator first,
                    InputIterator last,
                    Function f);                   // (1) C++03

  template <class InputIterator, class Function>
  constexpr Function for_each(InputIterator first,
                              InputIterator last,
                              Function f);         // (1) C++20

  template <class ExecutionPolicy, class ForwardIterator, class Function>
  void for_each(ExecutionPolicy&& exec,
                ForwardIterator first,
                ForwardIterator last,
                Function f);                       // (2) C++17
}

概要

イテレータ範囲[first, last)の全ての要素に、指定された関数を適用する。

要件

FunctionMoveConstructible の要件を満たす必要があるが、CopyConstructible の要件を満たす必要はない。(C++11のみ)

効果

[first,last) 内の全てのイテレータ if(*i) という操作を行う。first から順番に処理し、last - 1 まで行う。

このアルゴリズムはその他のアルゴリズムと違い、関数 f の内部で *i の値を書き換えても構わない(もちろんイテレータの型が mutable iterator の要件を満たしている場合に限る)。

戻り値

  • C++03 の場合 : f
  • C++11 の場合 : std::move(f)

計算量

正確に flast - first 回適用する

備考

  • f に戻り値がある場合、それは単に無視される
  • (1)は、戻り値の型がFunctionとなっている。シングルスレッドでの順次実行では関数オブジェクトfの状態を次々に変更していき、最終的な関数オブジェクトの状態を戻り値として取得できる
  • (2)の並列アルゴリズム版は、戻り値の型がFunctionではなくvoidとなっている。並列数だけ関数オブジェクトをコピーするため、関数オブジェクトの状態を順次変更していくような設計は、並列アルゴリズム版ではできないようになっている

C++03での例

#include <iostream>
#include <vector>
#include <algorithm>

void disp(int x) {
  std::cout << x << std::endl;
}

struct mutate {
  int n;
  mutate() : n(0) { }
  void operator()(int& v) {
    v += n++;
  }
};

int main() {
  std::vector<int> v;

  v.push_back(3);
  v.push_back(1);
  v.push_back(4);

  // vの全ての要素にdisp()関数を適用する
  std::for_each(v.begin(), v.end(), disp);

  std::cout << "----" << std::endl;

  // 要素の内容を書き換えても構わないし、呼び出し順序に依存した処理を書いても構わない
  std::for_each(v.begin(), v.end(), mutate());
  std::for_each(v.begin(), v.end(), disp);
}

出力

3
1
4
----
3
2
6

C++11での例

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
  std::vector<int> v = { 3, 1, 4 };

  // vの全ての要素にラムダ式を適用する
  std::for_each(v.begin(), v.end(), [](int x) { std::cout << x << std::endl; });

  std::cout << "----" << std::endl;

  // 要素の内容を書き換えても構わないし、呼び出し順序に依存した処理を書いても構わない
  int n = 0;
  std::for_each(v.begin(), v.end(), [n](int& x) mutable { x += n++; });
  std::for_each(v.begin(), v.end(), [](int x) { std::cout << x << std::endl; });
}

出力

3
1
4
----
3
2
6

処理系

  • Clang:
  • GCC:
  • ICC:
  • Visual C++: 2005, 2008, 2010, 2012, 2013, 2015
    • C++11への対応(戻り値のムーブ)は2012から。

実装例

template <class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f) {
  for ( ; first != last; ++first)
    f(*first);
  return move(f);
}

参照