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.

È stato utile?

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):

  1. Una firma funzione membro con parametri di default potrebbe essere sostituito da "due o più funzioni membro firme con un comportamento equivalente.
  2. Una firma funzione membro potrebbe avere parametri di default aggiuntivi.

Alla fine, Herb Sutter informati che

  1. Usa mem_fun, non solo con la libreria standard
  2. 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top