如何在std :: for_each中为一个lambda捕获std :: unique_ptr"by move"

Can*_*hiu 12 c++ lambda c++11

我正在学习c ++ 11中的新功能并遇到了这个问题.我想通过在lambda中移动它作为for_each的参数来捕获unique_ptr.

建立:

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

尝试1 - 不起作用,因为unique_ptr没有复制构造函数.c ++ 0x没有指定移动语法.

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

尝试2 - 使用bind将p的移动副本绑定到一个带有int&的函数:

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

编译器抱怨说 'result' : symbol is neither a class template nor a function template.

这个练习的主要目的是了解如何在lambda中捕获可移动变量,该lambda被缓存以供以后使用.

Ant*_*ams 19

更新:您可以从C++ 14开始捕获lambda中的可移动变量.

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

在C++ 11中,您无法以任何直接的方式将可移动变量捕获到lambda中.

通过复制或引用捕获Lambda.因此,要捕获仅移动变量,必须将其包装在复制=>移动(例如std::auto_ptr)的对象中.这是一个讨厌的黑客.

在您的示例中,您可以通过引用捕获,但如果这只是简化的代码,它可能无法使用实际代码执行您想要的操作:

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

这是一个仅复制移动的包装器:

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;
    }

};
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

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;
}
Run Code Online (Sandbox Code Playgroud)