function object with for_each() in C++

I am going to use a Sum function object in for_each() function to implement the sum of a vector. But I cannot get the sum result. below is code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

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


using namespace std;

class Sum
{
	int t;
public:
	
	Sum(int i):t(i){}

	void operator()(int a)
	{
		t+=a;
		cout <<"(a)" << a << "| t = " << t << endl; //trace the t value
	}
	int result()
	{
		return t; //to return object value
	}

};




int main()
{
	vector<int> vi;
	vi.push_back(1);
	vi.push_back(2);
	vi.push_back(3);

	Sum sum(0);

	for_each(vi.begin(),vi.end(),sum);

	cout <<"Sum result: " <<sum.result() << endl;

}



result is:
(a)1| t = 1
(a)2| t = 3
(a)3| t = 6
Sum result: 0


I expect the last line to return result 6 but it is 0.

I traced the processing in for_each() function, it seems work but it does not give me correct result.

Any advice is appreciated in advance.


My advice is to use std::accumulate(), which does exactly what you need with no need for
a function object.

 
std::cout << "The sum is " << std::accumulate( vi.begin(), vi.end(), 0 ) << std::endl;


As for what's wrong with your code: the problem is that the function object you pass to
std::for_each cannot maintain state per the STL requirements because std::for_each
will make a copy of the object to call operator()().

1
2
3
4
5
6
template<class InputIterator, class Function>
  Function for_each(InputIterator first, InputIterator last, Function f)
  {
    for ( ; first!=last; ++first ) f(*first);
    return f;
  }

As you see function takes "functor" by value(not by reference). It means that you has two objects:
The first of them it's Sum sum(0); (you created it explicitly).
The second is a copy of it.
for_each works with the copied object and the algorithm does not change your explicitly created object. But you can fix it by the following.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <algorithm>
#include <vector>


using namespace std;

class Sum
{
	int t;
public:
	
	Sum(int i):t(i){}

	void operator()(int a)
	{
		t+=a;
		cout <<"(a)" << a << "| t = " << t << endl; //trace the t value
	}
	int result() const
	{
		return t; //to return object value
	}

};




int main()
{
	vector<int> vi;
	vi.push_back(1);
	vi.push_back(2);
	vi.push_back(3);

	Sum sum(0);

	Sum summa = for_each(vi.begin(),vi.end(),sum);

	cout <<"Sum result: " <<summa.result() << endl;

}


And see jsmith's advice. If you need to get sum use accamulate.
jsmith, Denis, thank you very much. I had tried to find the solution by trace the process but I did not realise for_each takes copy rather than reference.

thank you very much!


Topic archived. No new replies allowed.