2013-10-13 16 views
8

Attualmente sto giocando con lambda di C++ 11 e ho trovato un esempio che non riesco a capire. Secondo la norma:Variabili lambda non locali e variabili di cattura: cosa significa "ambito di blocco" significa

A lambda-expression whose smallest enclosing scope is a block scope (3.3.3) is a local lambda expression; any other lambda-expression shall not have a capture-list in its lambda-introducer

così, ho creato esempio banale:

int a = 10; 
auto x = [a] { return 1;}; 
int main() { 
    int k = 5; 
    auto p = [k]{ return k; }; 
    return 0; 
} 

Il codice in Ideone: http://ideone.com/t9emu5

mi aspettavo che questo codice non viene compilato a causa della cattura variabile scope non-block (o almeno pensare che la parte auto x = ... non sia nel block-scope). Ma il codice è in fase di compilazione - va bene?

Se va bene, qual è lo scopo del blocco?

(non sono sicuro di quale versione del compilatore che usare perché al momento ho accesso solo al sito Ideone.

Grazie per la spiegazione!

+0

quindi, quale ambito è l'ambito non di blocco? – matekm

+1

@DanielFrey Huh? Un blocco è un'istruzione composta e uno spazio dei nomi non è certamente un blocco. Vedi [basic.scope.block]/1 e [stmt.block] – dyp

+0

@DyP Spiacente, mi sono confuso. Hai completamente ragione! –

risposta

12

Sembra che questo è un estensione del compilatore. G ++ 4.8 .1 compila questo dando un avvertimento:

warning: capture of variable ‘a’ with non-automatic storage duration [enabled by default]

clang ++ 3.4 non compilare questo:

error: 'a' cannot be captured because it does not have automatic storage duration

Entrambi si riferiscono a [expr.prim.lambda]/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.

Sembra che non controllano inoltre l'ambito racchiude del lambda, posso immaginare che sarebbe stato ridondante (non ci sono nomi di variabili con durata della memorizzazione automatica in ambito non blocco/spazio dei nomi).


Un ambito blocco è definito in [basic.scope.block]/1

A name declared in a block (6.3) is local to that block; it has block scope.

E un blocco è definito come:

So that several statements can be used where one is expected, the compound statement (also, and equivalently, called “block”) is provided.

     compound-statement:
         {statement-seqopt}

Quindi hai ragione che il vostro lambda globalmente dichiarato è non in un ambito di blocco.

+0

grazie mille! – matekm

+0

Per aggiungere: È possibile fare in modo che GCC lo respinga utilizzando il flag di compilazione '-pedantic-errors' (oltre a' -std = C++ 11'), che raccomando (e anche '-Wall -Wextra'). Ideone non ti consente di specificare le opzioni del compilatore, ma ad es. [Coliru] (http://coliru.stacked-crooked.com/) fa ([GCC Explorer] (http://gcc.godbolt.org/) anche, ma compila solo (e mostra l'output di assieme), non lo fa 't link ed esegui). (Vedi ad esempio http://isocpp.org/get-started per ulteriori compilatori C++ online.) –

+0

@gx_ Sembra essere sbagliato.Compilare con '-Wall -Wextra -Wpedantic' e non mi è mai stato detto di questo errore nel mio codice (che probabilmente è risultato spostando il lambda da un scope locale), attraverso' g ++ 'versione 5 e ora 6.1. Aggiungere '-pedantic-errors', piuttosto non sorprendentemente, non fa nulla per cambiare questo. 'g ++' semplicemente non mi avvisa. Suppongo di dover chiedere "clang ++" per un secondo parere più spesso ... sospiro –

Problemi correlati