Domanda

Sto cercando di usare l'algoritmo stl for_each senza proliferare template nel mio codice. std :: for_each vuole creare un'istanza della classe MyFunctor per valore, ma non può dal suo abstract. Ho creato una classe adattatore di funzione che passa un puntatore e poi lo dereferenzia quando appropriato.

La mia domanda:

STL o Boost hanno già una tale classe di adattatori? Non voglio reinventare la ruota!

 struct MyFunctor  {
     virtual ~MyFunctor() {}
     virtual void operator()(int a) = 0; 
 }

 namespace {
     template<typename FunctorType, typename OperandType> struct
 FunctorAdapter
     {
         FunctorAdapter(FunctorType* functor) : mFunctor(functor) {}
         void operator()(OperandType& subject)
         {
             (*mFunctor)(subject);
         }

         FunctorType* mFunctor;
     }; }

 void applyToAll(MyFunctor &f) {
     FunctorHelper<MyFunctor, int> tmp(&f);
     std::for_each(myvector.begin(), myvector.end(), tmp); }

Saluti,

Dave

È stato utile?

Soluzione

tr1 :: ref può aiutarti qui --- è pensato per essere un wrapper di riferimento in modo che tu possa passare oggetti normali facendo riferimento a oggetti bind o funzionali (anche astratti) facendo riferimento ad algoritmi standard.

// requires TR1 support from your compiler / standard library implementation
#include <functional>

void applyToAll(MyFunctor &f) {
    std::for_each(
        myvector.begin(), 
        myvector.end(), 
        std::tr1::ref(f) 
    ); 
}

Tuttavia, NOTA che i compilatori senza supporto declinazione MAGGIO rifiutano il passaggio di un riferimento a un tipo astratto ... quindi questo codice potrebbe non essere compilato finché non ottieni il supporto C ++ 0x.

Altri suggerimenti

È possibile utilizzare gli adattatori di funzione (e i relativi spessori) da funzionale .

#include <functional>

using namespace std;
for_each( vec.begin(), vec.end(), :mem_fun_ptr( &MyClass::f ) );

Se il tuo contenitore contiene puntatori ad oggetti, usa mem_fun_ptr , altrimenti usa mem_fun . Accanto a questi, ci sono wrapper per le funzioni membro che accettano 1 argomento: mem_fun1_ptr e mem_fun1 .

@Evan: in effetti, potresti chiamare la funzione membro con lo stesso argomento per ogni oggetto. Il primo argomento dei wrapper mem_fun1 è il puntatore this , il secondo è l'argomento della funzione membro:

for_each( vec.begin(), vec.end(), bind2nd( mem_fun_ptr( &MyClass::f ), 1 ) );

Con più argomenti, diventa più leggibile creare un ciclo da soli o creare un funzione personalizzata con variabili costanti che rappresentano gli argomenti.

Sembra che potresti trarre vantaggio da Boost :: Function .

Se ricordo bene che è anche una libreria di sola intestazione, quindi è facile farcela.

Che ne dici di dimenticare tutto il wrapping del puntatore functor e invece usare bind (functor_pointer, mem_fun1 (& amp; MyFunctor operatore :: ());  come il funzione? in questo modo, non devi preoccuparti di gestire la copia in alcun modo forma o forma.

Basandosi sulla risposta di @ xtofl, poiché l'array contiene int e non " this " puntatori, penso che l'incantesimo corretto sia

class MyClass
{
  virtual void process(int number) = 0;
};
MyClass *instance = ...;

for_each( vec.begin(), vec.end(), binder1st(instance, mem_fun_ptr(&MyClass::process) );

L'unica differenza rispetto al codice di @ xtofl è binder1st piuttosto che binder2nd. binder2nd ti consente di passare lo stesso numero a vari "questo" puntatori. binder1st ti consente di passare vari numeri a uno "questo". puntatore.

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