1

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?

vivekv80
  • 119
  • 5
  • 16
  • 1
    Hi, if you are iterating them anyways, why not just add this to your loop? `total_buf_size += it1.second;` –  Jun 24 '10 at 17:24
  • 1
    What do you mean by "all the values" in it1.second? It1.second is just an int. There's only value value in it. – Rob Kennedy Jun 24 '10 at 17:39
  • @ufotds sometimes the simplest step just solves the problem. I used what u mentioned `total_buf_size += it1.second;`. I was swayed in trying to use accumulate based on the STL examples for vector container. Also I was trying to avoid looping through the container. – vivekv80 Jun 24 '10 at 18:04
  • @Rob I meant the sum of all the values pointed by it1.second – vivekv80 Jun 24 '10 at 18:12
  • possible duplicate of [How to apply std::accumulate algorithm for associative containers?](http://stackoverflow.com/questions/6935118/how-to-apply-stdaccumulate-algorithm-for-associative-containers) –  Jan 03 '13 at 15:45

4 Answers4

2

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.
  • 287,565
  • 48
  • 449
  • 722
  • What I don't understand, wouldn't `accumulator` call the function with `buf_map` rather than its `buf_map.value_type` ? –  Jun 24 '10 at 17:43
  • @vivekv80: with backticks, but I don't know if it works for long sequences. – Matthieu M. Jun 25 '10 at 06:22
  • @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. Jun 25 '10 at 06:24
1

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
  • 95,107
  • 10
  • 109
  • 188
  • Doesn't work because the initializer is an `int` and `summ` does not take an `int` as parameter here. – Matthieu M. Jun 24 '10 at 17:31
  • 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/ –  Jun 24 '10 at 17:35
0

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);
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
Greg Domjan
  • 13,943
  • 6
  • 43
  • 59
0

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
  • 7,631
  • 2
  • 24
  • 30