2011-08-27 11 views
7

Ad esempio:regola per la variabile cattura lambda

class Example 
{ 
public: 
    explicit Example(int n) : num(n) {} 
    void addAndPrint(vector<int>& v) const 
    { 
     for_each(v.begin(), v.end(), [num](int n) { cout << num + n << " "; }); 
    } 
private: 
    int num; 
}; 

int main() 
{ 
    vector<int> v = { 0, 1, 2, 3, 4 }; 

    Example ex(1); 
    ex.addAndPrint(v); 
    return 0; 
} 

Quando si compila e si esegue questo in MSVC2010 si ottiene il seguente errore:

errore C3480: 'Esempio :: num': una cattura lambda variabile deve essere da un insieme di funzioni di inclusione

Tuttavia, con g ++ 4.6.2 (prerelease) si ottiene:

Quale compilatore ha ragione secondo la bozza standard? dice

+3

Si noti che è necessario acquisire 'this' per valore qui, non' num'. Quando usi 'num', stai veramente usando' this-> num'. Si noti inoltre che MSVC non implementa la dicitura C++ 11 di lambda, poiché è cambiata dopo il 2008, quando hanno implementato tutto questo. –

+0

@Alexandre: Catturare 'this' è effettivamente lo stesso di catturare' num' per riferimento. Questo sembra non essere ciò che si desidera qui. –

+0

@ Ben: buon punto. Comunque il risultato è lo stesso qui, poiché la chiusura non sfugge all'ambito di 'addAndPrint' (e l'intera faccenda dovrebbe comunque essere inserita qui). 5.1.2 come citato da @dimitri sembra indicare che MSVC ha ragione, dato che 'num' non è una variabile con durata di archiviazione automatica. Questo comportamento è piuttosto strano comunque. –

risposta

7

5.1.2/9:

The reaching scope of a local lambda expression is the set of enclosing scopes up to and including the innermost enclosing function and its parameters.

e 5.1.2/10:

The identifiers in a capture-list are looked up using the usual rules for unqualified name lookup (3.4.1); each such lookup shall find a variable with automatic storage duration declared in the reaching scope of the local lambda expression.

Come num è né dichiarata in qualsiasi ambito funzione né ha durata memorizzazione automatica, non può essere catturato . Quindi VS è giusto e g ++ è sbagliato.

+0

Grazie per il chiarimento. Ho scoperto che g + 4.6.2 ha qualche bug riguardante le acquisizioni, ad esempio '[=, this]' compila anche, e hanno intenzione di correggerle per 4.7.0. –

0

standard seguente (5.1.2):

Gli identificatori in una cattura-list vengono sguardo usando le regole usuali per la ricerca dei nomi non qualificati (3.4.1); ciascuna ricerca deve trovare una variabile con durata di archiviazione automatica dichiarata nell'ambito di portata dell'espressione lambda locale .

A mio giudizio, il compilatore GCC ha ragione perché "num" è nel raggio di raggiungimento del punto della dichiarazione lambda.

+2

Non è sufficiente essere in ambito, deve essere ** una variabile con durata di archiviazione automatica **. –

Problemi correlati