std::accumulate
From cppreference.com
| ヘッダー <numeric> で定義 |
||
template< class InputIt, class T > T accumulate( InputIt first, InputIt last, T init ); |
(1) | (C++20 以降 constexpr) |
template< class InputIt, class T, class BinaryOp > T accumulate( InputIt first, InputIt last, T init, BinaryOp op ); |
(2) | (C++20 以降 constexpr) |
与えられた値 init と範囲 [first, last) の要素の合計を計算します。
1) アキュムレータ acc (型は
T) を初期値 init で初期化し、その後、範囲 [first, last) 内のすべてのイテレータ i について、順に acc = acc + *i(until C++20)acc = std::move(acc) + *i(since C++20) で更新します。2) アキュムレータ acc (型は
T) を初期値 init で初期化し、その後、範囲 [first, last) 内のすべてのイテレータ i について、順に acc = op(acc, *i)(until C++20)acc = op(std::move(acc), *i)(since C++20) で更新します。次のいずれかの条件が満たされる場合、動作は未定義です。
-
Tは CopyConstructible ではありません。 -
Tは CopyAssignable ではありません。 - op は、
[first,last)の要素を変更しません。 - op は、
[first,last]のイテレータまたはサブ範囲を無効にしません。
目次 |
[編集] パラメータ
| first, last | - | 累積する要素の 範囲 を定義するイテレータのペア |
| init | - | 累積の初期値 |
| op | - | 適用される二項演算関数オブジェクト。 関数のシグネチャは以下と同等である必要があります。 Ret fun(const Type1 &a, const Type2 &b); シグネチャは const & を持つ必要はありません。 |
| 型要件 | ||
-InputIt は LegacyInputIterator の要件を満たす必要があります。 | ||
[編集] 戻り値
すべての変更後の acc。
[編集] 実装例
| accumulate (1) |
|---|
template<class InputIt, class T> constexpr // since C++20 T accumulate(InputIt first, InputIt last, T init) { for (; first != last; ++first) init = std::move(init) + *first; // std::move since C++20 return init; } |
| accumulate (2) |
template<class InputIt, class T, class BinaryOperation> constexpr // since C++20 T accumulate(InputIt first, InputIt last, T init, BinaryOperation op) { for (; first != last; ++first) init = op(std::move(init), *first); // std::move since C++20 return init; } |
[編集] 注釈
std::accumulate は左 フォールド を実行します。右フォールドを実行するには、二項演算子の引数の順序を逆にし、逆イテレータを使用する必要があります。
型推論に任せると、op は init と同じ型の値で操作されるため、イテレータ要素の意図しないキャストが発生する可能性があります。たとえば、v が std::vector<double> 型の場合、std::accumulate(v.begin(), v.end(), 0) は、おそらく期待する結果を与えないでしょう。
[編集] 例
このコードを実行
#include <functional> #include <iostream> #include <numeric> #include <string> #include <vector> int main() { std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int sum = std::accumulate(v.begin(), v.end(), 0); int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>()); auto dash_fold = [](std::string a, int b) { return std::move(a) + '-' + std::to_string(b); }; std::string s = std::accumulate(std::next(v.begin()), v.end(), std::to_string(v[0]), // start with first element dash_fold); // Right fold using reverse iterators std::string rs = std::accumulate(std::next(v.rbegin()), v.rend(), std::to_string(v.back()), // start with last element dash_fold); std::cout << "sum: " << sum << '\n' << "product: " << product << '\n' << "dash-separated string: " << s << '\n' << "dash-separated string (right-folded): " << rs << '\n'; }
出力
sum: 55 product: 3628800 dash-separated string: 1-2-3-4-5-6-7-8-9-10 dash-separated string (right-folded): 10-9-8-7-6-5-4-3-2-1
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 242 | C++98 | op には副作用があってはなりません。 | 関連する範囲を変更することはできません。 |
[編集] 関連項目
| 範囲内の隣接する要素間の差を計算する (関数テンプレート) | |
| 2つの範囲の要素の内積を計算する (関数テンプレート) | |
| 範囲の要素の部分和を計算する (関数テンプレート) | |
| (C++17) |
std::accumulate と似ていますが、順序が逆です。 (関数テンプレート) |
| (C++23) |
要素の範囲を左畳み込みする (アルゴリズム関数オブジェクト) |