You can also separate the 'take second of pair' functionality from 'calculate MULT*VAL' and 'add something to an accumulator'.
Though you don't need boost to do this, they already created a great deal of a 'functional' programming framework. If you can't use boost, you need some template magic of your own. Not too complicated, though.
#include <map>
#include <algorithm>
#include <numeric>
#include <functional>
#include <iostream>
Now I deem it 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;
}
};
This looks tricky, but is merely a generic way of saying: 'first do this, then do that 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, putting it all 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;
}