2011-03-29 16 views
11

En uno de los recientes C++ 0x corrientes de aire (n3225.pdf) podemos encontrar 5.1.2/10:C++ 0x lambda capturas

Los identificadores en una captura de lista se buscan utilizando las reglas habituales para la búsqueda de nombres no calificados (3.4.1); cada búsqueda encontrará una variable con la duración automática de almacenamiento declarada en el ámbito de alcance de la expresión lambda local. Se dice que una entidad (es decir, una variable o esto) se captura explícitamente si aparece en la lista de captura de la expresión lambda.

Eso parece bastante restrictivo para mí. Por ejemplo, se parece a mí que las siguientes cosas no están permitidos:

int global; 

struct s { 
    int x; 
    void memfun() { 
     [x,global]{}; 
    } 
}; 

desde x no es necesariamente una variable con el almacenamiento automático y tampoco lo es global. Tenga en cuenta que la intención de esta cláusula de captura es permitir que el objeto lambda almacene una copia de x y global que podría ser conveniente en caso de que se modifiquen en una etapa posterior. Ya soy consciente de una alternativa:

int global; 

struct s { 
    int x; 
    void memfun() { 
     int copyx = x; 
     int copyglobal = global; 
     [copyx,copyglobal]{}; 
    } 
}; 

Pero esto se reduce a copias extra y placa de la caldera adicional sólo para capturar x y global como copia.

Además, no puedo encontrar nada concluyente en las últimas corrientes de aire sobre lo que ocurre si nombramos una referencia local en la cláusula de captura:

int main() { 
    int i = 0; 
    int &r = i; 
    assert([r]{return &r;}() != &i); 
} 

¿El objeto lambda "copiar una referencia" o "copiar un int "¿?" Si captura el objeto referido por copia, esto puede salvarnos las copias adicionales de la solución de problemas anterior.

GCC aparentemente admite todos estos ejemplos y almacena una copia de un int en el último caso (que es deseable, en mi humilde opinión). Pero me gustaría saber si este es, de hecho, el comportamiento previsto de acuerdo con los borradores de C++ 0x o simplemente una extensión de compilador, respetivamente un error de implementación.

Editar:

templatetypedef señaló 5.1.2/14, que explica lo que sucede cuando una referencia se nombra en una cláusula de captura. Por lo que yo puedo decir, esto nos permite utilizar la siguiente solución temporal para el primer ejemplo:

int global; 

struct s { 
    int x; 
    void memfun() { 
     auto& cx = x; 
     auto& cglob = global; 
     [cx,cglob]{}; 
    } 
}; 

Tia, sellibitze

+0

Nota: C++ 14 extendió el conjunto de posibles cláusulas de captura – sellibitze

Respuesta

11

De lo que has publicado parece que su primer ejemplo es ilegal ya que ninguna de las variables capturadas tiene duración automática. Sin embargo, puede solucionarlo fácilmente. Para capturar el miembro de datos, puede capturar esto y no es necesario capturarlo, ya que puede hacer referencia directamente a él.

EDIT: Como ha señalado, esto no creará una copia local del valor que desea capturar. Para capturar estas variables al hacer una copia, puede capturar esto y luego crear explícitamente una copia local del miembro de datos dentro de la lambda.

En cuanto a la segunda pregunta acerca de las referencias captura, § 5.1.2/14 dice que la captura de una variable del tipo de referencia mediante copia creará una copia del valor de referencia en lugar de crear una copia de la referencia. Por lo tanto, la lambda tendrá su propia copia del valor al que hacía referencia la referencia cuando se creó.

+1

El punto de denominar 'x' y' global' en la cláusula de captura era permitir que el objeto lambda almacenara una * copia *. Esto podría ser deseable en caso de que ':: global' y' s :: x' cambien sus valores. Entonces, no, capturar 'esto' no conduce al comportamiento deseado. – sellibitze

+0

Estás en lo correcto; Acabo de actualizar mi respuesta. Gracias por señalar eso! – templatetypedef

+2

Gracias por señalar 5.1.2/14. Parece que podemos introducir referencias locales a variables no automáticas como una solución alternativa si estamos interesados ​​en capturar otras cosas mediante copia. – sellibitze

Cuestiones relacionadas