c++ - Al mover un unique_ptr a un lambda, ¿por qué no es posible llamar a reinicio?
c++11 unique-ptr (4)
- ¿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 esteoperator()
.
y
- ¿Es posible capturar
std::unique_ptr
de otra manera que permita llamar areset()
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
};
}
- ¿Por qué pasó esto?
-
¿Es posible capturar
std::unique_ptr
de otra manera que permita llamar areset()
dentro de la lambda (con C ++ 17 o posterior)?
- ¿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.
- ¿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();
};