std::accumulate
Header: <numeric>
std::accumulate accumulates elements in [first, last) as a left fold, starting from init.
The first overload updates the accumulator with operator+. The second overload updates it with a user-provided binary operation.
# Declarations
template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );
(constexpr since C++20)
template< class InputIt, class T, class BinaryOp >
T accumulate( InputIt first, InputIt last, T init, BinaryOp op );
(constexpr since C++20)
# Parameters
first, last: the input rangeinit: initial accumulator valueop: binary operation object used by overload (2). It must be callable with the current accumulator and an input element, and its result must be assignable toT.
op must not invalidate iterators or subranges in [first, last), and must not modify elements in that range.
# Type requirements
InputItmust meet the requirements of LegacyInputIterator.Tmust be CopyConstructible and CopyAssignable.
# Semantics
Let acc be the accumulator initialized from init.
- Overload (1): for each iterator
iin[first,last), performsacc = std::move(acc) + *i(since C++20; before C++20,acc + *i). - Overload (2): for each iterator
iin[first,last), performsacc = op(std::move(acc), *i)(since C++20; before C++20,op(acc, *i)).
# Return value
Final value of the accumulator after processing all elements.
# Complexity
Let N = std::distance(first, last).
- Overload (1): exactly
Napplications ofoperator+ - Overload (2): exactly
Napplications ofop
# Exceptions
Any exception thrown by operator+, op, iterator operations, or assignments to the accumulator is propagated.
# Notes
std::accumulate performs a left fold. To emulate a right fold, use reverse iterators and a matching operation order.
Type deduction for init matters. For example, std::accumulate(v.begin(), v.end(), 0) with v of type std::vector<double> performs integer accumulation and truncates intermediate results.
# Example
#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';
}
# Defect reports
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 242 | C++98 | op could not have side effects | it cannot modify the ranges involved |