Domanda

Mi chiedevo se qualcuno mi può aiutare con funtori. Io davvero non capisco cosa funtori sono e come funzionano Ho provato googling, ma io non ancora farlo. come si fa funtori lavoro e come funzionano con i modelli

È stato utile?

Soluzione

Un funtore è fondamentalmente un "oggetto funzione". Si tratta di una singola funzione che avete avvolto in una classe o struct, e che si può passare ad altre funzioni.

Essi lavorano con la creazione di una classe o struct che sovraccarica l'operatore di chiamata di funzione (chiamata operatore ()). In genere, si crea un'istanza di esso, semplicemente costruirla sul posto come argomento per la funzione che prende un funtore.

Si supponga di avere il seguente:

std::vector<int> counts;

Ora, si vuole incrementare tutti i conteggi che sono contenute in quel vettore. Si potrebbe scorrere manualmente per incrementare loro, o si potrebbe usare un funtore. Un functor adatto, in questo caso, sarebbe simile a questa:

struct IncrementFunctor
{
    int operator() (int i)
    {
        return i + 1;
    }
}

IncrementFunctor è ora un functor che prende qualsiasi numero intero e l'incrementa. Per applicarlo a conta, è possibile utilizzare lo std :: trasformare la funzione, che prende un funtore come argomento.

std::transform(
    counts.begin(),       // the start of the input range
    counts.end(),         // the end of the input range
    counts.begin(),       // the place where transform should place new values. 
                          // in this case, we put it right back into the original list.
    IncrementFunctor());  // an instance of your functor

L'IncrementFunctor sintassi () crea un'istanza di tale funtore che viene quindi passato direttamente a std :: trasformare. Si potrebbe, naturalmente, creare un'istanza come una variabile locale e trasmetterlo, ma questo è molto più conveniente.

Ora, su modelli. Il tipo di funtore in std :: trasformare è un argomento di template. Questo perché std :: trasformare non sa (o cura!) Di cui digitare il funtore è. Tutto ciò che preoccupa è che ha un operatore di raccordo () definito, per il quale si può fare qualcosa di simile

newValue = functor(oldValue);

Il compilatore è abbastanza intelligente sui modelli, e che spesso può capire da solo quello che gli argomenti di template sono. In questo caso, il compilatore capisce automaticamente che si sta passando un parametro di tipo IncrementFunctor, che è definito come un tipo di modello in std :: trasformare. Si fa lo stesso per la lista, anche, in modo che il compilatore riconosce automaticamente che la chiamata effettiva sarebbe simile a questa:

std::transform<std::vector<int>::iterator, // type of the input iterator
               std::vector<int>::iterator, // type of the output iterator
               IncrementFunctor>(          // type of your functor
    counts.begin(),       // the start of the input range
    counts.end(),         // the end of the input range
    counts.begin(),       // the place where transform should place new values. 
                          // in this case, we put it right back into the original list.
    IncrementFunctor());  // an instance of your functor

E 'consente di risparmiare un bel po' di battitura. ;)

Altri suggerimenti

Un funtore è qualcosa che può essere richiamato / chiamato con il la funzione di chiamata operatore , sintatticamente aggiungendo (), con opzionalmente una lista di argomenti all'interno delle parentesi.

Questo è tutto ha bisogno un modello. La cosa su cui questo è invocato, per quanto riguarda un modello è interessato, è tutto ciò che permette questa sintassi - o in altre parole, o una funzione libera o un'istanza di una classe che sostituisce operator()(). (Una funzione "libero" è solo uno che non è un membro, vale a dire, si tratta di una funzione in ambito globale o una funzione al perimetro di un namespace precedentemente incluse.)

Al di fuori di template metaprogrammazione, di solito non diciamo che una funzione libera è un un funtore, e riservano quel nome per un'istanza di una classe che sostituisce operator()():

struct Foo {
 public:
   void operator()( int i ) { // do something }
   void operator()( int i, char x ) { // do something else }
}

In template C ++ vengono compilati, in modo fino a quando il sintassi senso , il compilatore utilizzerà felicemente una funzione o un funtore:

template<typename T> class Bar {
  private int j ;
  public:
    Bar( int i ) : j(i) {}
    void doIt(T t) {
     t( j ) ;
  }
}

Foo f;
extern void resize( int i ) ; // in some header

Bar<Foo> bf( 5 ) ;
// a Bar that is templated on Foo
Bar< void (&)(int)   > br( 5 ) ; 
// a Bar that is templated on a function taking int and returning void

br.doit( &resize ) ; // call resize with br.j
bf.doit( f ) ; // call Foo::operator()(int) on Foo f with bf.j
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top