2011-08-27 13 views
7

Por ejemplo:Regla para la variable de captura 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; 
} 

Al compilar y ejecutar esto en MSVC2010 se obtiene el siguiente error:

C3480 de error: 'Ejemplo :: num': una captura de lambda variable debe ser de un ámbito de la función de cerramiento

Sin embargo, con g ++ 4.6.2 (preliminar) se obtiene:

¿Qué compilador está de acuerdo con el borrador estándar? dice

+3

Tenga en cuenta que tiene que capturar 'this' por valor aquí, no' num'. Cuando usas 'num', realmente estás usando' this-> num'. También tenga en cuenta que MSVC no implementa la redacción de C++ 11 de lambdas, ya que cambió después de 2008 cuando implementaron todo esto. –

+0

@Alexandre: Capturar 'this' es efectivamente lo mismo que capturar' num' por referencia. Eso parece no ser lo que se desea aquí. –

+0

@Ben: buen punto. Sin embargo, el resultado es el mismo aquí, ya que el cierre no escapa al alcance de 'addAndPrint' (y, de todos modos, es probable que todo esto quede incluido aquí). 5.1.2 citado por @dimitri parece indicar que MSVC tiene razón, ya que 'num' no es una variable con duración de almacenamiento automática. Sin embargo, este comportamiento es bastante extraño. –

Respuesta

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.

y 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.

Como num ni se declara en cualquier ámbito de la función ni tiene una duración de almacenamiento automático, que no puede ser capturado . Por lo tanto, VS es correcto y g ++ es incorrecto.

+0

Gracias por la aclaración. Descubrí que el g ++ 4.6.2 tiene algunos errores con respecto a las capturas, por ejemplo '[=, this]' también compila, y planean arreglarlos para 4.7.0. –

0

estándar lo siguiente (5.1.2):

Los identificadores en una captura de lista se levantó usando las reglas habituales de búsqueda de nombre no calificado (3.4.1); cada dicha búsqueda encontrará una variable con una duración de almacenamiento automática declarada en el alcance de la expresión lambda local .

Según entiendo, el compilador GCC tiene razón porque 'num' está en el alcance de alcance en el punto de la declaración lambda.

+2

No es suficiente estar dentro del alcance, tiene que ser ** una variable con duración de almacenamiento automática **. –

Cuestiones relacionadas