Domanda

È necessario per me usare std::function Ma non so cosa significhi la seguente sintassi.

std::function<void()> f_name = []() { FNAME(); };

Qual è l'obiettivo di usare std::function? È per fare un puntatore a una funzione?

È stato utile?

Soluzione

std::function è un oggetto di cancellazione del tipo. Ciò significa che cancella i dettagli di come si verificano alcune operazioni e fornisce loro un'interfaccia di runtime uniforme. Per std::function, il primario1 Le operazioni sono copia/mossa, distruzione e "invocazione" con operator() - La "funzione come operatore di chiamata".

In inglese meno astruso, significa che std::function Può contenere quasi tutti gli oggetti che si comportano come un puntatore di funzione nel modo in cui lo si chiama.

La firma che supporta va all'interno delle parentesi angolari: std::function<void()> Non prende argomenti e non restituisce nulla. std::function< double( int, int ) > ne prende due int argomenti e ritorni double. In generale, std::function Supporta la memorizzazione di qualsiasi oggetto simile a una funzione i cui argomenti possono essere convertiti dal suo elenco di argomenti e il cui valore di ritorno può essere convertito nel suo valore di restituzione.

È importante saperlo std::function E lembdas sono diverse, seppure compatibili, bestie.

La prossima parte della linea è una lambda. Questa è una nuova sintassi in C ++ 11 per aggiungere la possibilità di scrivere semplici oggetti simili a funzioni: oggetti che possono essere invocati (). Tali oggetti possono essere digitati e conservati in a std::function Al costo di un po 'di tempo di esecuzione.

[](){ code } In particolare è una lambda davvero semplice. Corrisponde a questo:

struct some_anonymous_type {
  some_anonymous_type() {}
  void operator()const{
    code
  }
};

Un'istanza del semplice tipo di pseudo-funzione semplice. Una classe effettiva come quella sopra è "inventata" dal compilatore, con un nome univoco definito implementazione (spesso inclusi simboli che non può contenere un tipo definito dall'utente) (non so se è possibile che tu possa seguire lo standard senza inventare Tale classe, ma ogni compilatore che conosco crea effettivamente la classe).

La sintassi completa di lambda sembra:

[ capture_list ]( argument_list )
-> return_type optional_mutable
{
  code
}

Ma molte parti possono essere omesse o lasciate vuote. Capture_list corrisponde sia al costruttore del tipo anonimo risultante che alle sue variabili membri, l'argomento_list gli argomenti del operator(), e il tipo di ritorno il tipo di ritorno. Il costruttore dell'istanza Lambda è anche magicamente chiamato quando l'istanza viene creata con cattura_list.

[ capture_list ]( argument_list ) -> return_type { code }

fondamentalmente diventa

struct some_anonymous_type {
  // capture_list turned into member variables
  some_anonymous_type( /* capture_list turned into arguments */ ):
    /* member variables initialized */
  {}
  return_type operator()( argument_list ) const {
    code
  }
};

Nota che in Gli argomenti dei modelli sono stati aggiunti a Lambdas e questo non è coperto sopra.

[]<typename T>( std::vector<T> const& v ) { return v.size(); }

1 Inoltre, RTTI è memorizzato (typeid) e è inclusa l'operazione di tipo cast-a-originale.

Altri suggerimenti

Rompi la linea:

std :: function

Questa è una dichiarazione per una funzione che non assume parametri e non restituire valore. Se la funzione restituiva un file int, sarebbe così:

std::function<int()>

Allo stesso modo, se ha preso anche un parametro INT:

std::function<int(int)>

Sospetto che la tua principale confusione sia la parte successiva.

[]() { FNAME(); };

Il [] la parte è chiamata a Clausola di cattura. Qui metti variabili locali alla dichiarazione del tuo lambda e che vuoi essere disponibile entro La funzione Lambda stessa. Questo sta dicendo "Non voglio che nulla venga catturato". Se questo fosse all'interno di una definizione di classe e volevi che la classe fosse disponibile per la lambda, potresti fare:

[this]() { FNAME(); };

La parte successiva, sono i parametri passati alla lambda, esattamente come se fosse una funzione regolare. Come menzionato prima, std::function<void()> è una firma che punta a un metodo che non richiede parametri, quindi anche questo è vuoto.

Il resto è il corpo della stessa lambda, come se fosse una funzione regolare, che possiamo vedere chiama semplicemente la funzione FNAME.

Un altro esempio

Supponiamo che tu abbia avuto la seguente firma, cioè qualcosa che può sommare due numeri.

std::function<int(int, int)> sumFunc;

Ora potremmo dichiarare così un lambda:

sumFunc = [](int a, int b) { return a + b; };

Non sono sicuro se stai usando MSVC, ma ecco comunque un link alla sintassi di espressione di Lamda:

http://msdn.microsoft.com/en-us/library/dd293603.aspx

Lambdas con catture (Lambdas statali) non possono essere assegnati l'uno all'altro poiché hanno tipi unici, anche se sembrano esattamente uguali. Per essere in grado di riporre e passare in giro con Lambdas con le catture, possiamo usare "std :: function"Tenere un oggetto funzione costruito da un'espressione di lambda. Fondamentalmente"std :: function"È, essere in grado di assegnare funzioni Lambda con diverse strutture di contenuto a un oggetto funzione Lambda.

Exp:

auto func = [](int a){
 cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //ATTENTION(ERROR!): assigning a new structure to the same object
 cout << "x:" << x << ",a:" << a << endl;
};
func(2);

Quindi l'utilizzo di cui sopra sarà errato. Ma se definiamo un oggetto funzione con "std :: function":

auto func = std::function<void(int)>{};
func = [](int a){
  cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //CORRECT. because of std::function
  //...
}; 

int y = 11;
func = [x,y](int a){ //CORRECT
 //...
}; 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top