È inoltre possibile separare la funzionalità "Prendi secondo della coppia" da "calcolare MULT * VAL" e "aggiungere qualcosa ad un accumulatore".
Anche se non è necessario potenziare per fare ciò, hanno già creato una grande quantità di un quadro di programmazione "funzionale". Se non puoi usare boost, hai bisogno di un modello magico per conto tuo. Non troppo complicato, tuttavia,.
#include <map>
#include <algorithm>
#include <numeric>
#include <functional>
#include <iostream>
Ora ritengo migliore per mettere la moltiplicazione all'interno della classe.
struct SMyStruct
{
int MULT;
int VAL;
long f() const { return MULT*VAL; }
};
Creare un funtore generico per 'prendere il secondo di coppia':
// 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;
}
};
Questo sembra difficile, ma è solo un modo generico per dire: 'prima fare questo, quindi farlo con il risultato ':
// 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); }
E, infine, mettere tutto in pratica:
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;
}
Aw, bb mi ha battuto per la risposta, quindi sarò un po 'pedante invece: sai che i principali underscore sono generalmente una cattiva idea, giusto? (riservato alla realizzazione nella maggior parte dei casi) E il prefisso S su una struttura è completamente privo di rumore. :) – jalf
argh, ok ... Beh abbiamo sempre prefisso le strutture con S e le classi con C; i nostri mandati standard di codifica. Nella misura in cui "_", sono d'accordo ma poiché non faceva parte di nulla, l'ho lasciato come tale. Solitamente uso m_ per i membri g_ per globals e s_ per static. Grazie per segnalarlo. –
_ * potrebbe * tecnicamente essere ok. Le regole sono qualcosa come "Il doppio comando _ O il comando _ seguito dalla lettera maiuscola è riservato all'implementazione." Il comando _ seguito da ogni altra cosa è riservato nello spazio dei nomi globale ".È più facile evitare semplicemente di condurre _'s complessivamente;) – jalf