2011-12-21 15 views
42

¿Es válida esta recursividad lambda?¿Es válido para una lambda, esencialmente, cerrar sobre sí mismo?

#include <functional> 
#include <iostream> 

int main() { 
    std::function<int(int)> g = [&g](int k) { 
     return (k ? k * g(k-1) : 1); 
    }; 

    std::cout << g(10); // 3628800 
} 

Se appears to compile and run ok, pero estoy nervioso por el cierre de más de g en el mismo comunicado que su inicialización. ¿Estricta validez en una escala de 1-10 ...?

+0

En C#, eso no compilaría; necesitarías dividirlo en dos declaraciones. – SLaks

+2

C++ 0x ejemplos [aquí] (http://zamjad.wordpress.com/2011/09/22/c-recursive-lambda-functions/) divídalo en 2 instrucciones, pero nunca explica por qué. – Joe

+0

Creo que es un comportamiento indefinido. Lambdas no está diseñado para recursividad porque es una función anónima, ¿verdad? – Hauleth

Respuesta

20

En el punto en el que se captura g por referencia, se ha declarado, por lo que el nombre está disponible para su uso:

3.3.2/1 El punto de la declaración de un nombre es inmediatamente después de su declarador completa (Cláusula 8) y antes de su inicializador

Usted está autorizado a utilizar los objetos de manera limitada antes de que se inicializan - básicamente, cualquier cosa que no depende del valor está bien:

3.8/6 antes de que se haya iniciado la vida útil de un objeto, pero después del almacenamiento que ocupará el objeto se ha asignado [...] cualquier glvalue que se refiera al objeto original pero solo en formas limitadas . [...] usar las propiedades del glvalue que no dependen de su valor está bien definido.

Por lo que entiendo, lo que está haciendo está bien definido.

(Aunque, siendo ultrapente, no creo que se especifique cuando se asigna el almacenamiento para un objeto automático, y 8.3.2/5 dice que "una referencia debe inicializarse para referirse a un objeto válido" sin definir "válido", por lo que hay margen para argumentar que no está bien definido).

+0

Estoy de acuerdo en que el enlace de una referencia no debe necesitar una conversión de valor a validación, pero la semántica del lenguaje en esta área es muy difícil de interpretar. :(Incluso para C++! –

+0

OK, creo que esto me satisface! –

+0

Estaba a punto de publicar esto: P Como cualquier definición de función, el código no se ejecuta en ese momento; 'g' no necesita un valor para el mismo razón 'k' no necesita un valor, desde la perspectiva de la definición.' g' se está usando con '[& g]', pero eso solo toma la dirección de la función futura. Y 'g' existe en ese punto porque las declaraciones ocurren antes de la asignación. –

Cuestiones relacionadas