Использование std:: accumulate
Требуется более красивое решение нижеприведенного примера, но с std:: accumulate.
#include <algorithm>
#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_;
};
class Calculator
{
public:
Calculator( double& result ):
result_( result )
{}
void operator() ( const Object& object )
{
// some formula
result_ += object.GetA() * object.GetB();
}
private:
double& result_;
};
int main()
{
std::vector< Object > collection;
collection.push_back( Object( 1, 2 ) );
collection.push_back( Object( 3, 4 ) );
double result = 0.0;
std::for_each( collection.begin(), collection.end(),
Calculator( result ) );
std::cout << "result = " << result << std::endl;
return 0;
}
Ответы
Ответ 1
делают изменения в калькуляторе и основной функции.
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;
}
также может быть лучше:
double sumABProduct( double result, const Object& obj )
{
return result + ( obj.GetA() * obj.GetB());
}
double result = std::accumulate( collection.begin(), collection.end(), 0, sumABProduct );
Ответ 2
Обновление 2: Boost.Lambda делает этот кусок пирога:
// 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;
Обновление: Это некоторое время прослушивало меня. Я не могу просто заставить любой алгоритм STL работать достойно. Итак, я сделал свой собственный:
// 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;
}
Конечно, исходное решение все еще выполняется:
Самый простой способ - реализовать operator+
. В этом случае:
double operator+(double v, Object const& x) {
return v + x.a_;
}
и сделайте его другом Object
или членом (посмотрите, почему вы можете предпочесть один из них):
class Object
{
//...
friend double operator+(double v, Object const& x);
и вы закончили с:
result = accumulate(collection.begin(), collection.end(), 0.0);
Мой предыдущий подход не работает, потому что нам нужен binary_function
.
std:: accumulate.
Ответ 3
вот здесь проблема, я думаю, что аргументы написаны в неправильном порядке:
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)) ; } };
в этом случае накапливается, результат содержится в возвращенном объекте.
Если вы используете gnu parallel mode, функтор даст вам проблемы, если результат и фактический объект, на который ссылается итератор, отличаются.
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())
не будет работать с параллельным режимом gnu по какой-то странной и глупой причине.
Ответ 4
Использование С++ 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;
}
Ответ 5
Можно было бы надеяться, что это домашняя работа...
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(), Object(0,0),Adapt() );
если вам не разрешено касаться объявления объекта.