views:

57

answers:

4

I have a multimap defined by

typedef std::pair<int, int> comp_buf_pair; //pair<comp_t, dij>
typedef std::pair<int, comp_buf_pair> node_buf_pair;
typedef std::multimap<int, comp_buf_pair> buf_map; //key=PE, value = pair<comp_t, dij>
typedef buf_map::iterator It_buf; 
int summ (int x, int y) {return x+y;}


int total_buf_size = 0;
std::cout << "\nUpdated buffer values" << std::endl;
for(It_buf it = bufsz_map.begin(); it!= bufsz_map.end(); ++it)
{
    comp_buf_pair it1 = it->second;
    // max buffer size will be summ(it1.second)
    //total_buf_size = std::accumulate(bufsz_map.begin(), bufsz_map.end(), &summ); //error??
    std::cout << "Total buffers required for this config = " << total_buf_size << std::endl;
    std::cout << it->first << " : " << it1.first << " : " << it1.second << std::endl;

}

I would like to sum all the values pointed by it1.second How can the std::accumulate function access the second iterator values?

+1  A: 

I think you'll just need to change your summ function to take the map value_type instead. This is totally untested but it should give the idea.

int summ (int x, const buf_map::value_type& y) 
{
    return x + y.second;
}

And call it:

total_buf_size = std::accumulate(bufsz_map.begin(), bufsz_map.end(), 0, &summ);

Mark B
Doesn't work because the initializer is an `int` and `summ` does not take an `int` as parameter here.
Matthieu M.
I think it actually needs to take in a buf_map, and and return a temporary buf_map with the second being set to the sum in order to work. See: http://www.cplusplus.com/reference/std/numeric/accumulate/
ufotds
A: 

Accumulate is a generalization of summation: it computes the sum (or some other binary operation) of init and all of the elements in the range [first, last).

... The result is first initialized to init. Then, for each iterator i in [first, last), in order from beginning to end, it is updated by result = result + *i (in the first version) or result = binary_op(result, *i) (in the second version).

Sgi.com

Your attempt was neither first or second version, you missed the init part

total_buf_size = std::accumulate(bufsz_map.begin(), bufsz_map.end(), 0, &summ);
Greg Domjan
A: 

Why do you mess about with pairs containing pairs? It is too complicated and you'll wind up making errors. Why not define a struct?

Michael J
This would not solve the issue... but thanks anyway, I guess.
Matthieu M.
+2  A: 

Your issue is with the summ function, you actually need something better than that to be able to handle 2 mismatched types.

If you're lucky, this could work:

int summ(int x, buf_map::value_type const& v) { return x + v.second; }

If you're unlucky (depending on how accumulate is implemented), you could always:

struct Summer
{
  typedef buf_map::value_type const& s_type;
  int operator()(int x, s_type v) const { return x + v.second.first; }
  int operator()(s_type v, int x) const { return x + v.second.first; }
};

And then use:

int result = std::accumulate(map.begin(), map.end(), 0, Summer());
Matthieu M.
What I don't understand, wouldn't `accumulator` call the function with `buf_map` rather than its `buf_map.value_type` ?
ufotds
@Matthieu unlucky option using structs did work:)`struct Summer``{` typedef buf_map::value_type const int operator()(int x, s_type v) const { return x + v.second.second; } int operator()(s_type v, int x) const { return x + v.second.second; }};’Needed to sum the second value pointed by the second iterator
vivekv80
@Matthieu ahh how does code get highlighted in comments? hmm.
vivekv80
@vivekv80: with backticks, but I don't know if it works for long sequences.
Matthieu M.
@ufotds: `accumulate` is a STL algorithm which hides the loop, the function you supply must work with the type you wish in return (accumulated result) on the one hand and the type yielded by dereferencing an iterator in the other.
Matthieu M.