std::accumulate
ja.cppreference.net より
| ヘッダ <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 で初期化し、範囲 acc = acc + *i(C++20 まで)acc = std::move(acc) + *i(C++20 から) 内の各イテレータ i に対して順に [first, last) で変更します。2) アキュムレータ
acc (型 T) を初期値 init で初期化し、範囲 acc = op(acc, *i)(C++20 まで)acc = op(std::move(acc), *i)(C++20 から) 内の各イテレータ i に対して順に [first, last) で変更します。以下のいずれかの条件が満たされる場合、動作は未定義です。
Tが CopyConstructible ではない。Tが CopyAssignable ではない。opが[first,last)の要素を変更する。opが[first,last]内の任意のイテレータまたはサブ範囲を無効にする。
引数
| first, last | - | 累積する要素の 範囲 を定義するイテレータのペア |
| init | - | 累積の初期値 |
| op | - | 適用される二項演算関数オブジェクト。 関数のシグネチャは以下と同等である必要があります。
シグネチャに |
| 型要件 | ||
-InputIt は LegacyInputIterator の要件を満たす必要があります。
| ||
戻り値
acc すべての変更後の
。
| 実装例 |
|---|
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 (1) |
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;
}
|
accumulate (2)
std::accumulate注釈 は左 畳み込み
を行います。右畳み込みを行うには、二項演算子の引数の順序を逆にし、逆方向イテレータを使用する必要があります。
op型推論に任せた場合、init は std::accumulate(v.begin(), v.end(), 0) と同じ型の値に対して操作するため、イテレータの要素が意図しないキャストになる可能性があります。例えば、v の型が std::vector<double> の場合、
は望ましい結果を与えない可能性があります。
例
#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) |
範囲の要素を左畳み込みする (アルゴリズム関数オブジェクト) |