You can also separate the “take a second pair” function from “calculate MULT * VAL” and “add something to the battery”.
Despite the fact that you do not need momentum for this, they have already created many functional software frameworks. If you cannot use boost, you need template magic. However, not too difficult.
#include <map> #include <algorithm> #include <numeric> #include <functional> #include <iostream>
Now I think it's better to put the multiplication inside the class.
struct SMyStruct { int MULT; int VAL; long f() const { return MULT*VAL; } };
Create a generic functor for 'take second of pair':
// 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; } };
It looks complicated, but it’s just a general way of saying, “First do it and then do it with the result”:
// 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 ); }
And finally, all this in practice:
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; }