Qual è il tipo di lambda quando dedotto con “auto” in C ++ 11?

Ho avuto la percezione che, il tipo di lambda è un puntatore a funzione. Quando ho eseguito il test successivo, ho trovato che fosse sbagliato ( demo ).

#define LAMBDA [] (int i) -> long { return 0; } int main () { long (*pFptr)(int) = LAMBDA; // ok auto pAuto = LAMBDA; // ok assert(typeid(pFptr) == typeid(pAuto)); // assertion fails ! } 

Il codice sopra manca qualsiasi punto? In caso contrario, qual è il typeof espressione lambda quando viene dedotta con auto parola chiave auto ?

Il tipo di espressione lambda non è specificato.

Ma in genere sono solo zucchero sintattico per i funtori. Una lambda è tradotta direttamente in un funtore. Qualsiasi cosa all’interno di [] viene trasformata in parametri costruttore e membri dell’object functor, ei parametri inside () vengono trasformati in parametri per l’ operator() del functor operator() .

Un lambda che non cattura nessuna variabile (nulla all’interno di [] ) può essere convertito in un puntatore di funzione (MSVC2010 non supporta questo, se questo è il tuo compilatore, ma questa conversione è parte dello standard).

Ma il vero tipo di lambda non è un puntatore a funzione. È un tipo di functor non specificato.

È una struttura unnamed unica che sovraccarica l’operatore di chiamata di funzione. Ogni istanza di una lambda introduce un nuovo tipo.

Nel caso speciale di una lambda non catturante, la struttura in aggiunta ha una conversione implicita in un puntatore di funzione.

[C++11: 5.1.2/3]: il tipo di espressione lambda (che è anche il tipo dell’object di chiusura) è un tipo di class non unione univoco, non denominato, chiamato tipo di chiusura , le cui proprietà sono descritto sotto. Questo tipo di class non è un aggregato (8.5.1). Il tipo di chiusura è dichiarato nel più piccolo scope, scope della class o scope del namespace che contiene la lambda-expression corrispondente. [..]

La clausola continua ad elencare le varie proprietà di questo tipo. Ecco alcuni punti salienti:

[C++11: 5.1.2/5]: il tipo di chiusura per un’espressione lambda ha un operatore di chiamata di funzione inline pubblica (13.5.4) i cui parametri e tipo di ritorno sono descritti dalla dichiarazione dei parametri dell’espressione lambda -clause e trailing-return-type rispettivamente. [..]

[C++11: 5.1.2/6]: Il tipo di chiusura per un’espressione lambda senza lambda-capture ha una funzione di conversione const non-public pubblica non-virtuale per puntare a una funzione che ha lo stesso parametro e tipi di ritorno come l’operatore di chiamata di funzione del tipo di chiusura. Il valore restituito da questa funzione di conversione deve essere l’indirizzo di una funzione che, invocata, ha lo stesso effetto del richiamo dell’operatore di chiamata di funzione del tipo di chiusura.

La conseguenza di questo passaggio finale è che, se si utilizzava una conversione, sarebbe ansible assegnare LAMBDA a pFptr .

 #include  #include  #define LAMBDA [] (int i)->long { return 0l; } int main () { long (*pFptr)(int) = LAMBDA; // ok auto pAuto = LAMBDA; // ok std::cout< 

I tipi di funzione sono effettivamente uguali, ma la lambda introduce un nuovo tipo (come un functor).

Una soluzione pratica di Come posso memorizzare un object boost :: bind come membro della class? , prova boost::function o std::function .

Dovrebbe anche notare che lambda è convertibile in puntatore a funzione. Tuttavia, typeid <> restituisce un oggetto non trittico che dovrebbe differire da lambda al puntatore di funzione generico. Quindi il test per typeid <> non è un’ipotesi valida. In generale, C ++ 11 non vuole che ci preoccupiamo delle specifiche del tipo, tutto ciò che importa se un determinato tipo è convertibile in un tipo di destinazione.