2012-07-17 11 views
6

El estándar de C++ 11 dice (o al menos, la versión que tengo - no el final):¿Por qué la "lambda implícita para funcionar la conversión del puntero" prohíbe la captura "por referencia" de miembros estáticos?

El tipo de cierre para un lambda-expresión con sin lambda-captura tiene un pública la función de conversión const non-virtual no-virtual al puntero para funcionar teniendo el mismo parámetro y tipos de retorno que el operador de llamada de función del tipo del cierre.

Entiendo por qué no es posible obtener un puntero de función de un lambda con estado dado que un puntero de función no puede contener ningún dato por sí mismo.

Pero cuando los objetos capturados son solo miembros estáticos/variable estática, no existe tal limitación ya que las referencias a los objetos capturados se pueden cablear en la función misma.

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 
    } 
}; 

¿Por qué no siempre es posible convertir un lambda en un puntero de función tan pronto como el primero no tiene estado? ¿Me estoy perdiendo algo o el comité olvidó este punto específico?

+1

Supongo que es para evitar que los compiladores puedan probar mucho sobre lo que se está capturando. – Flexo

+0

El compilador ya puede capturar variables automáticamente tan pronto como se utilizan (usando el [&] automático), por lo que no requerirá mucho más trabajo verificar si son miembros estáticos o globales, ya que necesariamente sido declarado antes –

+0

En realidad, no lo he probado en ningún compilador (solo tengo MSVC10 que no admite ninguna conversión de puntero a función). ¿Supongo que es una extensión de GCC? De todos modos, mi pregunta es: está permitido por el estándar (tal vez me perdí algo)? Si no, ¿por qué está prohibido (tal vez haya una limitación técnica que desconozco)? –

Respuesta

9

A::count no necesita ser capturado en absoluto. Solo se deben capturar this y las variables locales. Las variables con duración de almacenamiento estático (por ejemplo, miembros de datos estáticos, variables de ámbito de espacio de nombres o variables estáticas de función local) no necesitan capturarse porque son "únicas". Hay exactamente una instancia de cada variable, por lo que no es necesario capturar una referencia al objeto.

Si elimina la captura predeterminada de su lambda (es decir, cambie [&] a []) y defina count, debería compilarse sin error. (He verificado que tanto Visual C++ 2012 RC como g ++ 4.5.1 aceptan el código, el único cambio que tuve que hacer fue mover la inicialización en línea de count, ya que ninguno de esos compiladores aún soporta la característica C++ 11.)

+0

Sí, por supuesto ... Me siento estúpido ahora :) Pero, ¿y si queremos capturar una variable local estática? –

+0

Tampoco es necesario capturarlos, por la misma razón: cada variable local estática es "única" y tiene una dirección conocida. He modificado la respuesta para hacer referencia a "variables con duración de almacenamiento estático". Todavía puede haber algunas sutilezas aquí, aunque ninguna de las que conozco (y VC11 y g ++ 4.5.1 aceptan el programa con 'count' como una variable de ámbito de espacio de nombres, un miembro de datos estáticos, o como una función- local estático). –

+0

¡No sabía que estaba permitido, gracias! –

Cuestiones relacionadas