From: "dmoore99atwork" <dmoore@ashtontechgroup.com>
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.