programacion lambdas expresiones examples c++ objective-c lambda c++11 objective-c++

c++ - expresiones - lambdas java



Objetivo-C++ 11-¿Por qué no podemos asignar un bloque a un lambda? (2)

Por lo tanto, acabo de actualizar a Xcode 4.4, y me di cuenta en el registro de cambios:

El compilador Apple LLVM admite funciones adicionales de C ++ 11, incluidas lambdas

¡Lo cual es asombroso! Así que me puse a codificar, y encontré algunas cosas:

  1. Lambdas se pueden asignar a bloques Objective-C:

    void (^block)() = []() -> void { NSLog(@"Inside Lambda called as block!"); }; block();

  2. std::function puede contener un bloque Objective-C:

    std::function<void(void)> func = ^{ NSLog(@"Block inside std::function"); }; func();

  3. No podemos asignar un bloque Objective-C a un lambda:

    auto lambda = []() -> { NSLog(@"Lambda!"); }; lambda = ^{ // error! NSLog(@"Block!"); }; lambda();

¿Por qué es esto? ¿No deberían los dos ser semánticamente equivalentes, dado lo que hemos visto arriba?


Lambdas tiene sus propios tipos definidos por la implementación que son específicos para cada lambda. El siguiente código también es un error:

auto l1=[](){return 1;} auto l2=[](){return 2;} l1=l2; //Error

std::function es un contenedor diseñado para contener cualquier tipo de llamante; deberías usar eso para mantener callables que pueden ser de diferentes tipos.


El operador de copia-asignación de lambda de C ++ 11 está explícitamente deshabilitado 1 . Esto no es una cuestión de "semánticamente equivalente". Ni siquiera se puede asignar a sí mismo. Por no mencionar un tipo no relacionado.

#include <cstdio> #include <type_traits> int main() { auto lambda1 = []() -> void { printf("Lambda 1!/n"); }; lambda1 = lambda1; // error: use of deleted function ‘main()::<lambda()>& main()::<lambda()>::operator=(const main()::<lambda()>&)’ return 0; }

std::function puede contener un bloque Objective-C.

  • std::function puede contener cualquier tipo que se pueda invocar como f(a,b,c,...) . Dado que los bloques son compatibles con "el operador de invocación", también puede ser retenido por una std::function . Pero observe que Objective-C y C ++ siguen un esquema de gestión de memoria diferente, por lo que almacenar un bloque en una std::function durante mucho tiempo puede causar una referencia variable.

Lambdas se pueden asignar a bloques Objective-C:

  • Culpa SAHChandler 2 :). Sin embargo, aún no está documentado.

1 : C ++ 11 §5.1.2 / 19:

El tipo de cierre asociado con una expresión lambda tiene un constructor predeterminado eliminado (8.4.3) y un operador de asignación de copia eliminado.

2 : http://llvm.org/viewvc/llvm-project?view=rev&revision=150620