On 03/08/2018 04:03 AM, Ralf Goertz wrote:
> Hi,
>
> I wondered why there is no std::accumulate function
There is: it's in <numeric> and defined in section 29.8.2 of the standard:
> template <class InputIterator, class T>
> T accumulate(InputIterator first, InputIterator last, T init);
> template <class InputIterator, class T, class BinaryOperation>
> T accumulate(InputIterator first, InputIterator last, T init,
> BinaryOperation binary_op);
> 1 Requires: T shall meet the requirements of CopyConstructible > (Table 24) and CopyAssignable (Table 26) types. In the range [first,
> last], binary_op shall neither modify elements nor invalidate
> iterators or subranges. 281
> 2 Effects: Computes its result by initializing the accumulator
> acc with the initial value init and then modifies it with
> acc = acc +*i or acc = binary_op(acc, *i) for every iterator i in
> the range [first, last) in order. 282
~/testprog(115) cat accumulate.cpp
#include <iostream>
#include <numeric>
#include <vector>
int main(void) {
std::vector<int> v{{6,2,3}};
std::cout << std::accumulate(v.begin(), v.end(), 0L) << std::endl;
return 0;
}
~/testprog(116) g++ -std=c++1y -pedantic -Wall -Wpointer-arith
-Wcast-align -ffor-scope -fno-gnu-keywords -fno-nonansi-builtins
-Wctor-dtor-privacy -Wnon-virtual-dtor -Wold-style-cast
-Woverloaded-virtual -Wsign-promo accumulate.cpp -o accumulate
~/testprog(117) ./accumulate
11
...
The fundamental problem here is that a gets passed to std::copy<>() by
value. In other words, the third parameter of std::copy() is a separate
instance of Accum<int>, initialized with a copy of the values stored in
a. All that accumulation occurs inside the copies of that object which
std::copy<>() creates. The value of a itself remains completely unchanged.
> cout<<*a<<endl;
And therefore, it does not reflect the accumulation that has occurred.
In order to do what you want done, 'n' should exist outside of the
iterator. Initialize your iterator from a pointer or reference to that
object, and have copy/assignment of your iterator produce a new iterator
that points/refers to the same external object as the original. Then
your code should work (unless it has some other flaw I haven't noticed yet).