如果lambda使用std :: move()捕获不可复制的对象,为什么它不可移动?

Ben*_*ahi 7 c++ lambda function move c++14

这是我生成错误的示例代码:

#include <functional>
using namespace std;

struct S {
    S() = default;
    S(const S&) = delete;
    S(S&&) = default;
    S& operator=(const S&) = delete;
    S& operator=(S&&) = delete;
};

template <typename F>
void post(F&& func)
{
    function<void()> f{forward<F>(func)};
}

int main()
{
    S s;
    post([s2 = move(s)] { });
}
Run Code Online (Sandbox Code Playgroud)

拉姆达在里面main(),我捕捉到局部变量s使用std::move().在调用post()之前,s2必须已成功移动构造.

但是,在里面post(),f不能使用对该lambda类型的rvalue引用构造.

如果我删除,s2 = move(s),f可以用这个右值引用来构建.

为什么添加s2 = move(s)渲染lambda不可移动?

在这里,是一个尝试coliru 的链接.

Rei*_*ica 12

通过移动捕获,您的lambda不会变得不可移动.但它确实变得不可复制,这是一个问题.

std::function不支持将提供的仿函数移动到自身,它总是复制.因此,不可复制的lambda(和其他callable)不能使用std::function.这种限制的原因是标准要求std::function是可复制的,如果用不可复制的可调用语句初始化则无法实现.

  • @BenjiMizrahi没有.你很困惑*将一个仿函数移动到`std :: function`*并且*移动`std :: function`对象本身.*前者是不可能的,而后者是完全正常的(和*移动)*实际存储的算子).前者不可能的原因是标准要求`std :: function`是可复制的,如果它可以从不可复制的仿函数中构造,则无法实现. (4认同)