说我有一个
struct SMyStruct
{
int MULT;
int VAL;
};
std::map<std::string, SMyStuct*> _idToMyStructMap;
现在我想计算所有SMyStuct的总和,其中total被定义为idToMyStructMap中每个元素的MULT1 * VAL1 + MULT2 * VAL2。
似乎累积功能是一个自然的选择。请建议。感谢
请不要提升......只是'时尚stl
答案 0 :(得分:13)
typedef std::map< std::string, SMyStruct* > string_to_struct_t;
int add_to_totals( int total, const string_to_struct_t::value_type& data )
{
return total + data.second->MULT * data.second->VAL;
}
const int total = std::accumulate(
_idToMyStructMap.begin(),
_idToMyStructMap.end(),
0,
add_to_totals );
答案 1 :(得分:6)
主题的变体是为你的struct定义operator +,然后在默认模式下使用std :: accumulate。
int & operator+ (const int &lhs, const SMyStruct &rhs){
return lhs + (rhs.MULT * rhs.VALUE);
}
然后:
std::accumulate(_idToMyStructMap.begin(), _idToMyStructMap.end(), 0);
当然,如果operator+
对于你的结构有一般意义,那么你也想在左边添加使用SMyStruct的重载,和/或使它们成为模板以便你获得int的函数所有在一个镜头中,浮动,双倍,长,等。正如jalf在评论中提到的那样,如果operator+
(或它的这个版本)对你的结构一般没有意义,那么另一个解决方案就更好了。
答案 2 :(得分:1)
您还可以将“计算第二对”功能与“计算MULT * VAL”和“将某些内容添加到累加器”分开。
虽然你不需要提升来做到这一点,但他们已经创建了大量的“功能”编程框架。如果你不能使用boost,你需要一些你自己的模板魔法。但是,太复杂了。
#include <map>
#include <algorithm>
#include <numeric>
#include <functional>
#include <iostream>
现在我认为将乘法放在类中更好。
struct SMyStruct
{
int MULT;
int VAL;
long f() const { return MULT*VAL; }
};
为'第二对'创建一个通用仿函数:
// a 'take-second' functor
template< typename at_pair >
struct to_second_t : public std::unary_function< at_pair, typename at_pair::second_type > {
const typename at_pair::second_type& operator()( const at_pair & p ) const {
return p.second;
}
};
这看起来很棘手,但仅仅是一种通用的说法:'首先这样做,然后用结果做到:'
// compose two functors (simplified)
template< typename at_F, typename at_G >
struct compose_t : public std::unary_function< typename at_F::argument_type, typename at_G::result_type >{
at_F f;
at_G g;
compose_t( at_F& f, at_G& g ): f( f ), g(g) {}
typename at_G::result_type operator()( const typename at_F::argument_type& v ) const {
return g( f( v ) );
}
};
template< typename at_F, typename at_G >
compose_t<at_F, at_G> compose( at_F& f, at_G& g ) { return compose_t<at_F,at_G>( f, g ); }
// compose two functors (a unary one, and a binary one)
//
template< typename at_F, typename at_G >
struct compose2_t : public std::binary_function< typename at_F::first_argument_type, typename at_G::argument_type, typename at_G::result_type >{
at_F f;
at_G g;
compose2_t( at_F& f, at_G& g ): f( f ), g(g) {}
typename at_G::result_type operator()( const typename at_F::first_argument_type& a1, const typename at_G::argument_type& v ) const {
return f( a1, g( v ) );
}
};
template< typename at_F, typename at_G >
compose2_t<at_F, at_G> compose2( at_F& f, at_G& g ) { return compose2_t<at_F,at_G>( f, g ); }
最后,将其全部付诸实践:
int main()
{
typedef std::map<int, SMyStruct > tMap;
tMap m;
SMyStruct s = {1,2};
m[1].VAL = 1; m[1].MULT = 3;
m[2].VAL = 2; m[2].MULT = 10;
m[3].VAL = 3; m[3].MULT = 2;
// mind, this is not LISP (yet)
long total = std::accumulate( m.begin(), m.end(), 0,
compose2(
std::plus<int>(),
compose(
to_second_t<tMap::value_type>(),
std::mem_fun_ref( &SMyStruct::f ) ) )
);
std::cout << "total: " << total <<std::endl;
return 0;
}