|
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