Domanda
Sto avendo difficoltà a capire mem_fun_ref
. Devo ammettere, io di solito uso funtori per questo genere di cose, in quanto possono essere inline per la velocità e il profitto. Tuttavia, questo codice non sta andando essere un collo di bottiglia e così ho voluto provare questa cosa.
Ecco un esempio di quello che voglio fare. So che ci sono altri modi per farlo. Non voglio usare copy
, non voglio usare le funzioni di membro gamma, non voglio usare un back_inserter
. In particolare mi voglio usare mem_fun_ref
. Questo è solo un semplice esempio, il caso reale è molto più complicato. Detto questo, io davvero non so perché questo è sbagliato, ma io non ho familiarità con mem_fun_ref
o mem_fun
.
Ecco quello che voglio lavorare:
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
list<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
vector<int> b;
// should work like magic!
for_each(a.begin(), a.end(), bind1st(mem_fun_ref(&vector<int>::push_back), b));
}
Ma ho 3 errori:
1>c:\program files\microsoft visual studio 9.0\vc\include\functional(276) : error C2529: '_Right' : reference to reference is illegal
1>c:\program files\microsoft visual studio 9.0\vc\include\functional(281) : error C2529: '_Right' : reference to reference is illegal
1>c:\program files\microsoft visual studio 9.0\vc\include\functional(282) : error C2535: 'void std::binder1st<_Fn2>::operator ()(const int &(&)) const' : member function already defined or declared
1> with
1> [
1> _Fn2=std::mem_fun1_ref_t<void,std::vector<int>,const int &>
1> ]
1> c:\program files\microsoft visual studio 9.0\vc\include\functional(276) : see declaration of 'std::binder1st<_Fn2>::operator ()'
1> with
1> [
1> _Fn2=std::mem_fun1_ref_t<void,std::vector<int>,const int &>
1> ]
reference to reference is illegal
mi fa pensare che la funzione ha bisogno di prendere un parametro per valore. Ma, naturalmente, questo non è possibile cambiare in vector
, e non è possibile modificarlo nel mio codice sia. C'è una semplice modifica per ottenere questo lavoro? Ho bisogno di una soluzione che è un 1-liner.
Soluzione
Basta usare bind
. Le versioni mem_fun
sono troppo difficili.
for_each(a.begin(), a.end(),
boost::bind(&vector<int>::push_back, boost::ref(b), _1));
Un altro modo che non richiede l'uso di ref
è passare un puntatore al vettore da modificare:
for_each(a.begin(), a.end(),
boost::bind(&vector<int>::push_back, &b, _1));
Altri suggerimenti
Questo problema è stato spiegato nel "++ stile eccezionale C" di Herb Sutter, pag 28-30. Uno probabilmente non in grado di creare in modo sicuro un puntatore ad un metodo vector<int>::push_back
come uno ha bisogno di essere sicuri della firma esatta della funzione di membro, che non può essere evidente anche per vector<int>::push_back
nella libreria standard. Questo perché (in Standard Library):
- Una firma funzione membro con parametri di default potrebbe essere sostituito da "due o più funzioni membro firme con un comportamento equivalente.
- Una firma funzione membro potrebbe avere parametri di default aggiuntivi.
Alla fine, Herb Sutter informati che
- Usa mem_fun, non solo con la libreria standard
- Usa puntatori a funzioni membro, non solo con la libreria standard
So che hai detto che non vuoi utilizzare back_inserter
, probabilmente perché hai dato solo codice di esempio semplificato.
Per chiunque altro chiedendo come fare esattamente quello che stai cercando di fare, e felice di usarlo, l'uso back_inserter
:
std::copy(a.begin(), a.end(), std::back_inserter(b));
Detto questo, c'è sempre other_mem_fun
, che ho cucinato prima che sapevo di spinta. Questo potrebbe andare bene.