将带有unique_ptr的可变lambda传递给const&std :: function

Tom*_*Tom 7 c++ lambda c++14

我有一个调度函数,它在主线程中执行给定的lambda.为了这个问题,假设它看起来如下:

void dispatch(const std::function<void()>& fn) {
    fn();
}
Run Code Online (Sandbox Code Playgroud)

我需要在新线程中加载一个新对象而不会中断主线程.所以我执行以下操作:1)启动一个新线程并在线程内创建一个新的唯一指针,2)调用dispatch并传播它所属的新唯一指针.

std::unique_ptr<std::string> foo; // nullptr

// do the loading in a new thread:
std::thread t([&](){
    // in the new thread, load new value "Blah" and store it temporarily
    auto bar = std::make_unique<std::string>("Blah");
    dispatch([bar2 = std::move(bar), &foo]() mutable {
        foo = std::move(bar2); // propagate the loaded value to foo
    });
});
t.join(); // for the sake of this example

std::cout << "foo = " << *foo << std::endl; // this should say: foo = Blah
Run Code Online (Sandbox Code Playgroud)

在线运行示例:http://cpp.sh/5zjvm

这段代码不能编译,因为内部lambda in dispatchmutable,因此不适合dispatch(const std::function<void()>& fn)需要a const&.

然而,lambda需要是mutable因为它需要调用std::move唯一的指针.

此代码可以修复,例如通过更改dispatch为:

template <typename Fn>
void dispatch(Fn fn) {
    fn();
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,该dispatch函数是库的API,我无法更改它.

如果没有摆脱独特的指针,有没有办法摆脱这个问题?

Yak*_*ont 8

不,那不是你的问题.

你的问题是你的lambda无法复制,因为它有一个由值中捕获的唯一ptr.

std::function<Sig> 类型删除到

  1. 调用 Sig

  2. 破坏

  3. 复制(有时移动)

  4. 铸造回至原来的型

您的lambda无法复制,因此无法存储在std::function.

懒惰编码器的解决方案是:

    dispatch([bar2 = std::make_shared<decltype(bar)>(std::move(bar)), &foo]() mutable {
        foo = std::move(*bar2);
    });
Run Code Online (Sandbox Code Playgroud)

我们把不可复制的状态推到了一个地方shared_ptr.