c++ c++11 lambda unique-ptr capture-list

c++ - Al mover un unique_ptr a un lambda, ¿por qué no es posible llamar a reinicio?



c++11 unique-ptr (4)

  1. ¿Por qué pasó esto?

Debido a que el operador de llamada de función de un lambda ,

A menos que la palabra clave mutable se haya utilizado en la expresión lambda, el operador de llamada de función está constan- calificado y los objetos que fueron capturados por copia no son modificables desde este operator() .

y

  1. ¿Es posible capturar std::unique_ptr de otra manera que permita llamar a reset() dentro de la lambda?

Necesitas marcarlo como mutable .

mutable: permite al cuerpo modificar los parámetros capturados por copia y llamar a sus funciones miembro no constantes

p.ej

auto l = [v = std::move(u)]() mutable { v.reset(); };

Cuando se mueve std::unique_ptr en la lambda, no es posible llamar a reset() en él, porque parece ser constante entonces:

error C2662: void std::unique_ptr<int,std::default_delete<_Ty>>::reset(int *) noexcept'': cannot convert ''this'' pointer from ''const std::unique_ptr<int,std::default_delete<_Ty>>'' to ''std::unique_ptr<int,std::default_delete<_Ty>> &

#include <memory> int main() { auto u = std::unique_ptr<int>(); auto l = [v = std::move(u)]{ v.reset(); // this doesn''t compile }; }

  1. ¿Por qué pasó esto?
  2. ¿Es posible capturar std::unique_ptr de otra manera que permita llamar a reset() dentro de la lambda (con C ++ 17 o posterior)?

  1. ¿Por qué pasó esto?

Porque las lambdas son por defecto no mutables. Por lo tanto todos los objetos capturados son const. reset es una función miembro no constante que modifica el puntero único.

  1. ¿Es posible capturar std :: unique_ptr de otra manera que permita llamar a reset () dentro de la lambda (con C ++ 17 o posterior)?

Sí. Declarar la lambda mutable:

[captures](arguments) mutable { body } ^^^^^^^

Esto es posible desde C ++ 11 donde se introdujeron las lambdas. Todos los objetos no constantes capturados de un lambda mutable son copias no constantes.


Dentro de la lambda sus miembros de datos son inmutables por defecto. Debe agregar el especificador mutable a la expresión lambda.

Como alternativa, puede capturar el unique_ptr por referencia, como por ejemplo:

#include <memory> int main() { auto u = std::unique_ptr<int>(); auto l = [&v = u]{ v.reset(); }; }


Para mutar un "miembro" de la lambda, necesita la palabra clave mutable :

auto l = [v = std::move(u)] () mutable { v.reset(); };