c++ lambda move c++14

c++ - Mover un lambda: una vez que haya movido-capturado un tipo de solo movimiento, ¿cómo se puede usar el lambda?



c++14 (2)

Esta pregunta ya tiene una respuesta aquí:

Esta respuesta explica cómo mover y capturar una variable dentro de un lambda en C ++ 14.

Pero una vez que haya movido-capturado un objeto que no se puede copiar (como un std::unique_ptr ) dentro de un lambda, no puede copiar el mismo lambda.

Esto estaría bien si pudieras mover la lambda, pero obtengo un error de compilación cuando intento hacerlo:

using namespace std; class HasCallback { public: void setCallback(std::function<void(void)>&& f) { callback = move(f); } std::function<void(void)> callback; }; int main() { auto uniq = make_unique<std::string>("Blah blah blah"); HasCallback hc; hc.setCallback( [uniq = move(uniq)](void) { std::cout << *uniq << std::endl; }); hc.callback(); }

Esto produce el siguiente error con g++ (he intentado copiar solo la línea relevante):

error: use of deleted function ‘main()::<lambda()>::<lambda>(const main()::<lambda()>&’

... implicando, creo, que mi intento de mover la lambda ha fallado.

clang++ da un error similar.

Intenté move explícitamente la lambda (aunque es un valor temporal), pero eso no ayudó.

EDITAR: Las respuestas a continuación abordan adecuadamente los errores de compilación producidos por el código anterior. Para un enfoque alternativo, simplemente release el valor objetivo del puntero único en un std::shared_ptr , que se puede copiar. (No escribo esto como una respuesta, porque eso supondría que se trata de un problema XY, pero es importante entender la razón subyacente por la que unique_ptr no se puede usar en un lambda que se convierte en una std::function unique_ptr . )

EDIT 2: lo suficientemente hilarante, me di cuenta de que auto_ptr realidad haría lo correcto aquí (!), Por lo que puedo decir. Actúa esencialmente como unique_ptr , pero permite copiar-construcción en lugar de mover-construcción.


Puedes mover la lambda , eso está bien. Sin embargo, ese no es el problema, estás intentando crear una instancia de una std::function con un lambda que no se puede copiar. Y el:

template< class F > function( F f );

constructor de function hace:

5) Inicializa el objetivo con una copia de f .

Esto es porque std::function :

Satisface los requisitos de CopyConstructible y CopyAssignable.

Dado que la function debe poder copiarse, todo lo que coloque en ella también debe poder copiarse. Y un lambda de solo movimiento no cumple con ese requisito.


std::function no es un lambda! Es un envoltorio que se puede construir a partir de cualquier tipo de llamable, incluido un lambda. std::function requiere que el invocable sea construible por copia , por lo que su ejemplo falla.

Una lambda de solo movimiento se puede mover de nuevo como se muestra a continuación.

template<typename F> void call(F&& f) { auto f1 = std::forward<F>(f); // construct a local copy f1(); } int main() { auto uniq = make_unique<std::string>("Blah blah blah"); auto lambda = [uniq = move(uniq)]() { std::cout << *uniq << std::endl; }; // call(lambda); // doesn''t compile because the lambda cannot be copied call(std::move(lambda)); }

Demo en vivo