Need prettier solution of below example but with std::accumulate.
#include
#include
#include
class Object
{
pu
Update 2: Boost.Lambda makes this a piece of cake:
// headers
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
// ...
cout << accumulate(dv.begin(), dv.end(),
0,
_1 += bind(&strange::value, _2)) //strange defined below
<< endl;
Update: This has been bugging me for a while. I can't just get any of the STL algorithms to work in a decent manner. So, I rolled my own:
// include whatever ...
using namespace std;
// custom accumulator that computes a result of the
// form: result += object.method();
// all other members same as that of std::accumulate
template <class I, class V, class Fn1, class Fn2>
V accumulate2(I first, I last, V val, Fn1 op, Fn2 memfn) {
for (; first != last; ++first)
val = op(val, memfn(*first));
return val;
}
struct strange {
strange(int a, int b) : _a(a), _b(b) {}
int value() { return _a + 10 * _b; }
int _a, _b;
};
int main() {
std::vector<strange> dv;
dv.push_back(strange(1, 3));
dv.push_back(strange(4, 6));
dv.push_back(strange(20, -11));
cout << accumulate2(dv.begin(), dv.end(),
0, std::plus<int>(),
mem_fun_ref(&strange::value)) << endl;
}
Of course, the original solution still holds:
The easiest is to implement an operator+
. In this case:
double operator+(double v, Object const& x) {
return v + x.a_;
}
and make it a friend of Object
or member (look up why you may prefer one over the other):
class Object
{
//...
friend double operator+(double v, Object const& x);
and you're done with:
result = accumulate(collection.begin(), collection.end(), 0.0);
My earlier approach doesn't work because we need a binary_function
.
std::accumulate manual.
do changes in Calculator and main function.
struct Calculator
{
double operator() ( double result, const Object& obj )
{
return result + ( obj.GetA() * obj.GetB());
}
};
int main()
{
std::vector< Object > collection;
collection.push_back( Object( 1, 2 ) );
collection.push_back( Object( 3, 4 ) );
double result = std::accumulate( collection.begin(), collection.end(), 0, Calculator() );
std::cout << "result = " << result << std::endl;
return 0;
}
also it could be better:
double sumABProduct( double result, const Object& obj )
{
return result + ( obj.GetA() * obj.GetB());
}
double result = std::accumulate( collection.begin(), collection.end(), 0, sumABProduct );
here is an issue here, I guess the arguments are written in the wrong order should be:
result = std::accumulate(collection.begin(), collection.end(), Object(0),Adapt())
where Adapt is defined thus:
struct Adapt {
static double mul(Object const &x) { return x.GetA() * x.GetB(); }
static Object operator()(Object const &x, Object const &y) {
return Object(mul(x)+mul(y)) ; } };
in this case of accumulate, the result is contained in a returned Object.
If you are using gnu parallel mode the functor will give you problems if the result and the actual object referred to by the iterator are different.
struct Adapt {
static double mul(Object const &x) { return x.GetA() * x.GetB(); }
static double operator()(Object const &x, Object const &y) {
return mul(x)+mul(y) ; } };
result = std::accumulate(collection.begin(), collection.end(), 0.0,Adapt())
will not work with gnu parallel mode for some strange and silly reason.
One would hope this is homework...
struct Adapt {
static double mul(Object const &x) { return x.GetA() * x.GetB(); }
static double operator()(Object const &x, Object const &y) {
return mul(x)+mul(y); } };
and
result = std::accumulate(collection.begin(), collection.end(), Object(0,0),Adapt() );
assuming you're not allowed to touch the declaration of Object.
Using c++0x:
#include <numeric>
#include <vector>
#include <iostream>
class Object
{
public:
Object( double a, double b ):
a_( a ),
b_( b )
{}
double GetA() const { return a_; }
double GetB() const { return b_; }
// other methods
private:
double a_;
double b_;
};
int main()
{
std::vector< Object > collection;
collection.push_back( Object( 1, 2 ) );
collection.push_back( Object( 3, 4 ) );
double result = std::accumulate( collection.begin(), collection.end(), 0,
[] (double result, const Object& obj)
{
return result + obj.GetA() * obj.GetB();
}
);
std::cout << "result = " << result << std::endl;
return 0;
}