Boost logo

Boost Users :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2001-12-15 11:04:23


From: "dmoore99atwork" <dmoore_at_[hidden]>
> Hello,
>
> I'm trying to explore the compose, bind, and mem_fn libraries. I
> used a "real" problem I'm having. Given a vector<Trade>, I want to
> gather a sum of the return values of Trade::volume().
>
>
> I wound up writing "accumulate_with_op" thusly:
[...]

As Douglas already pointed out, std::accumulate has a version that takes a
binary function object that can be used to do the job.

However, I've found that the easiest way to solve these problems is to
simply use for_each, like this:

void add(double & a, double b) { a += b; }

double sum = 0.0;

std::for_each(trades.begin(), trades.end(), bind(add, ref(sum),
bind(&Trade::volume, _1)));

As you can see from the above, bind can compose, so you don't need
compose_f_gx.

> I tried for a long time to use combinations of for_each,
> compose_f_gx, and mem_fn to be able to do the Sum (to lead to other
> things like mean, stddev) into a stateful function object.
> Something like this:
>
> /* broken code, trying to convery my intentions */
> MeanValue m1;
> m1 = for_each(l.begin(), l.end(),compose_f_gx(MeanValue(),mem_fun_ref
> (&Trade::volume));
> cout << m1.result();

I'm not sure that I understand correctly your intent, but this might be what
you want:

#include <boost/bind.hpp>

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

struct Trade
{
 double volume() const
 {
  return 1.0;
 }
};

class Mean
{
public:

 Mean(): sum_(0.0), count_(0)
 {
 }

 void update(double v)
 {
  sum_ += v;
  ++count_;
 }

 double value() const
 {
  return sum_ / count_;
 }

private:

 double sum_;
 int count_;
};

void add(double & a, double b) { a += b; }

int main()
{
 std::vector<Trade> trades(5);

 Mean m;

 std::for_each(trades.begin(), trades.end(), boost::bind(&Mean::update, &m,
boost::bind(&Trade::volume, _1)));

 std::cout << m.value() << '\n';
}

Variations are possible as well; you may opt to keep the sum and the count
separate and just write a helper update:

void update(double & sum, int & count, double v)
{
    sum += v;
    ++count;
}

and then use

double sum = 0.0;
int count = 0;

std::for_each(trades.begin(), trades.end(), bind(update, ref(sum),
ref(count), bind(&Trade::volume, _1)));

like the first example.

HTH

--
Peter Dimov
Multi Media Ltd.

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net