Problem with Function Object

I am trying to write a function object to add the integer values in the map. I have an error in the use of msi as an argument in my function sum. See boldfaced.

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
//    C21 I-O.cpp
#include <iostream>
#include <map>
#include <string>
#include <sstream>
#include <numeric>
#include <functional>

int sum(const std::pair<std::string, int>& e, int v) {
	return v + e.second;
}


std::ostream& operator<< (std::ostream& os, const std::map< std::string, int >& map) {

	os << "{ ";
	for (const auto& pair : map) os << "{'" << pair.first << "'," << pair.second << "} ";
	return os << "}";
}

std::istream& operator>> (std::istream& is, std::map<std::string, int>& map) {

	map.clear();

	std::string str;
	int i;
	while (is >> str >> i) map.emplace(str, i);

	if (!map.empty()) { is.clear(); is.ignore(1000, '\n'); }
	return is;
}

int main() {

	std::map<std::string, int> msi;			// instantiate object msi

	std::istringstream str_in("map 34 set 9 string 26 vector 5 istream 1001 stringbuf 87");  // Input data into str_in
	str_in >> msi;

	std::cout << msi << '\n';

	int v = 0;
	int total = std::accumulate(msi.begin(), msi.end(), v, sum(msi, v)); // msi
}
Last edited on
1) You have wrong order of arguments to the sum function. Accumulate passes previous sum as first parameter.

2) You need to pass a function, not call result. Get rid of call operator:
std::accumulate(msi.begin(), msi.end(), v, sum);
I am trying to write a function object...


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
#include <iostream>
#include <map>
#include <string>
#include <algorithm>

// Now a function object!
struct Summer {
    int operator()(int v,  const std::pair<std::string, int>& e) const {
        return v + e.second;
    }
};

int main() {
    std::map<std::string, int> msi;
    msi.emplace("one", 1);
    msi.emplace("two", 2);
    msi.emplace("three", 3);
    msi.emplace("five", 5);
    msi.emplace("seven", 7);

    int v = 0;
    int total = std::accumulate(msi.begin(), msi.end(), v, Summer());
    std::cout << "total = " << total << "\n";

    return 0;
}


Andy
Surely using that type of function object is pointless now that we have std::function?
shadowmouse wrote:
Surely using that type of function object is pointless now that we have std::function?

std::function does not define function objects. It just provides us with a generic way to handle things that can behave like functions, such as the function object defined above.

If you were speaking of lambdas that would make more sense, but lambdas are not the panacea of function objects.
MiiNiPaa,

I did as you said, and the program worked beautifully.

andywestkin,

You're right. I did not write a function object but wrote a function instead. I honestly did not know until I re-read the section on function objects. I am glad, however, I wrote the function first because as you can see I did not know how to write the function. The mistakes I made were worth the learning experience. Thank you, MiiNiPaa.

I used your function object in my program but it did not work. I get too many parameters for this operator function for lines 14 and 21 in my code above.

shadowmouse,

A function object is an object that can behave like a function. You use an object because it can store data. The function call operator()implements the "function call".

Leading up from the function and the function object is the lambda expression. From the function, I was able to see the lambda expression,
[](int v, std::pair<const std::string, int>& e) { return v + e.second; } . I used it as the last argument in the accumulate algorithm.

A lambda expression is a short hand notation for defining a function object. It can be found in one place as opposed to a function or function object.
I used your function object in my program but it did not work. I get too many parameters for this operator function for lines 14 and 21 in my code above.

The code fragment I posted runs using C+ Shell so you can see how it's supposed to be used.

But I don't get why you should get an error on lines 14 and 21 -- these lines have absolutely nothing to do with the function object (they're the insertion and extraction operators for your map, yes?)

Andy
Andy,

Your function object works. I deleted out all my comments to start anew and the red squiggly lines disappeared. Essentially, I had commented out the function and lambda expression and inserted your function object. So, the error must have been that I did not comment out a code fragment.

Sorry for the confusion. My apologies.

Thank you for your help.
Topic archived. No new replies allowed.