c++ - funciones - std::function




Cómo capturar std:: unique_ptr "por movimiento" para un lambda en std:: for_each (2)

Actualización: puede capturar una variable móvil en una lambda desde C ++ 14 en adelante.

std::for_each(arr.begin(), arr.end(), [p=std::move(p)](int& i) { i+=*p; });

No se puede capturar una variable móvil en una lambda de manera directa en C ++ 11.

Lambdas captura por copia o por referencia. Por lo tanto, para capturar una variable solo de movimiento, debe envolverla en un objeto donde copiar => mover (como std::auto_ptr ). Este es un hack desagradable.

En su ejemplo, puede simplemente capturar por referencia, pero si se trata de un código simplificado, puede que no haga lo que usted quería con el código real:

std::for_each(arr.begin(), arr.end(), [&p](int& i) { i+=*p; });

Aquí hay un contenedor de copia solo para mover:

template<typename T>
struct move_on_copy_wrapper
{
    mutable T value;

    move_on_copy_wrapper(T&& t):
        value(std::move(t))
    {}

    move_on_copy_wrapper(move_on_copy_wrapper const& other):
        value(std::move(other.value))
    {}

    move_on_copy_wrapper(move_on_copy_wrapper&& other):
        value(std::move(other.value))
    {}

    move_on_copy_wrapper& operator=(move_on_copy_wrapper const& other)
    {
        value=std::move(other.value);
        return *this;
    }

    move_on_copy_wrapper& operator=(move_on_copy_wrapper&& other)
    {
        value=std::move(other.value);
        return *this;
    }

};

Puede usarlo así:

int main()
{
    std::unique_ptr<int> p(new int(3));
    move_on_copy_wrapper<std::unique_ptr<int>> mp(std::move(p));

    [mp]()
    {
        std::cout<<"*mp.value="<<*mp.value<<std::endl;
    }
    ();

    std::cout<<"p="<<p.get()<<", mp="<<mp.value.get()<<std::endl;
}

Estoy aprendiendo las nuevas características en c ++ 11 y encontré este problema. Me gustaría capturar un unique_ptr moviéndolo dentro de un lambda como argumento para for_each.

preparar:

std::array<int,4> arr = {1,3,5,6};
std::unique_ptr<int> p(new int);  (*p) = 3;

intento 1 - no funciona porque unique_ptr no tiene un constructor de copia. c ++ 0x no especifica la sintaxis paso por paso.

std::for_each(arr.begin(), arr.end(), [p](int& i) { i+=*p; });

intento 2 - use bind para vincular una copia movida de p a una función que toma int &:

std::for_each(arr.begin(), arr.end(),
     std::bind([](const unique_ptr<int>& p, int& i){
          i += (*p);
     }, std::move(p))
);

El compilador se queja de que 'result' : symbol is neither a class template nor a function template.

El objetivo principal del ejercicio es comprender cómo se puede capturar una variable móvil en una lambda almacenada en caché para su uso posterior.


Tu intento 2 casi funcionará.

Lo que falta es que no le has dicho a tu llamada de bind que espere un parámetro:

std::for_each(arr.begin(), arr.end(),
   std::bind([](const unique_ptr<int>& p, int& i){
      i += (*p);
   }, std::move(p), std::placeholders::_1)
);

Los placeholders::_1 son necesarios para indicar el resultado del bind que debe esperar que se le pase un parámetro a su operator() .

Esta es también la sugerencia dada en la respuesta de @ marton78 aquí .





c++11