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

时间:2018-10-26 18:29:00

标签: c++ lambda c++14

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

void dispatch(const std::function<void()>& fn) {
    fn();
}

我需要在不中断主线程的情况下在新线程中加载新对象。因此,我执行以下操作: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

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

此代码无法编译,因为dispatch中的内部lambda是mutable,因此不适合需要dispatch(const std::function<void()>& fn)的{​​{1}}。

但是,lambda必须为const&,因为它需要在唯一指针上调用mutable

例如,可以通过将std::move更改为以下代码来固定该代码:

dispatch

不幸的是,template <typename Fn> void dispatch(Fn fn) { fn(); } 函数是库的API,我无法对其进行更改。

有没有摆脱唯一指针的方法来解决这个问题?

1 个答案:

答案 0 :(得分:6)

不,那不是你的问题。

您的问题是您的lambda无法复制,因为它具有按值捕获的唯一ptr。

std::function<Sig>类型会擦除为

  1. 使用Sig

  2. 调用
  3. 消灭

  4. 复制(有时移动)

  5. 原始回复类型

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

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

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

我们将不可复制状态推送到shared_ptr