2012-07-17 12 views
6

Lo standard C++ 11 afferma (o almeno, la versione che ho - non quella finale):Perché l'implicito "lambda to function pointer conversion" non consente l'acquisizione "per riferimento" di membri statici?

Il tipo di chiusura per una lambda espressione con senza lambda-capture ha un pubblica funzione di conversione const non esplicita non virtuale al puntatore per funzionare con gli stessi parametri e tipi di ritorno della chiusura operatore di chiamata di funzione del tipo .

Capisco perché non è possibile ottenere un puntatore a funzione da un lambda stateful poiché un puntatore a funzione non può contenere alcun dato da solo.

Ma quando gli oggetti catturati sono solo membri statici/variabile statica, non esiste tale limitazione poiché i riferimenti agli oggetti catturati possono essere cablati nella funzione stessa.

struct A { 
    static int count = 0; 
    void foo() { 
     static int bar = 0; 
     auto fun = [&]()->void { 
      count++; 
      bar++; 
     }; 
     void(*ptrFun)(); 
     ptrFun = fun; // forbidden by the quoted wording 
    } 
}; 

Perché non è sempre possibile convertire un lambda in un puntatore di funzione non appena il primo è stateless? Mi manca qualcosa o il comitato ha dimenticato questo punto specifico?

+1

Direi che è per evitare che i compilatori siano in grado di dimostrare qualcosa su ciò che viene catturato. – Flexo

+0

Il compilatore è già in grado di acquisire automaticamente le variabili non appena vengono utilizzate (utilizzando l'automatico [&]), quindi non richiederà molto più lavoro per verificare se sono membri statici o globali poiché hanno necessariamente stato dichiarato prima. –

+0

In realtà non l'ho testato su nessun compilatore (ho solo MSVC10 che non supporta affatto la conversione del puntatore a funzione). Immagino sia un'estensione GCC? Ad ogni modo, la mia domanda è: è permessa dallo standard (forse mi sono perso qualcosa)? Se no, perché è vietato (forse c'è una limitazione tecnica che non conosco)? –

risposta

9

A::count non ha bisogno di essere catturato affatto. Solo this e le variabili locali devono essere catturate. Le variabili con durata di archiviazione statica (ad es. Membri di dati statici, variabili dello scope dei nomi o variabili statiche locali) non devono essere catturate perché sono "uniche". Esiste esattamente un'istanza di ciascuna di queste variabili, quindi non è necessario acquisire un riferimento all'oggetto.

Se si rimuove l'acquisizione predefinita dal lambda (ad esempio, cambia [&] in []) e si definisce count, deve essere compilato senza errori. (Ho verificato che sia Visual C++ 2012 RC che g ++ 4.5.1 accettino il codice, l'unico cambiamento che ho dovuto fare è stato spostare l'inizializzazione inline di count, poiché nessuno di questi compilatori supporta ancora la funzionalità di C++ 11.)

+0

Sì, certo ... Mi sento stupido ora :) Ma, cosa succede se vogliamo catturare una variabile locale statica? –

+0

Inoltre, non è necessario catturarli, per lo stesso motivo: ogni variabile locale statica è "univoca" e ha un indirizzo noto. Ho modificato la risposta per fare riferimento a "variabili con durata di archiviazione statica". Potrebbero esserci ancora alcune sottigliezze qui, anche se nessuna delle quali sono a conoscenza (e VC11 e g ++ 4.5.1 accettano entrambi il programma con 'count' come variabile dello scope dei nomi, un membro statico dei dati o come funzione- locale statico). –

+0

Non sapevo che fosse permesso, grazie! –

Problemi correlati