C++ 无法为 lambda 中捕获的 Promise 调用 set_value ?

MHe*_*bes 4 c++ boost-asio c++11 std-future

我正在尝试编写一个相当简单的方法来返回未来。lambda 决定了未来。这是一个最小的例子。实际上,lambda 可能会在不同的线程中调用,等等。

#include <future>

std::future<std::error_code> do_something() {
  std::promise<std::error_code> p;
  auto fut = p.get_future();
  auto lambda = [p = std::move(p)] {
    std::error_code error;
    p.set_value(error);
  };
  lambda();
  return std::move(fut);
}

int main() { return do_something().get().value(); }
Run Code Online (Sandbox Code Playgroud)

由于某种原因,我收到类型错误。VSCode 智能感知 说:

没有重载函数“ std::promise<_Ty>::set_value [with _Ty=std::error_code]”的实例与参数列表和对象匹配(该对象具有阻止匹配的类型限定符) -- 参数类型为: ( std::remove_reference_t<std::error_code &>) -- 对象类型为:const std::remove_reference_t<std::promise<std::error_code> &>

MSVC 编译器说:

错误 C2663: ' std::promise<std::error_code>::set_value': 2 个重载没有对 ' this' 指针进行合法转换

我真的不明白 VS Code 错误。它是说它认为error是 aconst promise<error_code>吗?如何正确调用lambda 捕获中的set_value承诺?move

Art*_*oul 5

默认情况下,lambda 将所有捕获的值(非引用)存储为const值,您无法修改它们。但lambda支持关键字mutable,你可以这样添加:

[/*...*/](/*...*/) mutable { /*...*/ }

这将允许 lambda 的内部修改其所有值。

如果由于某种原因您无法使用mutable,那么您可以使用其他解决方法:

[/*...*/, p = std::make_shared<ClassName>(std::move(p)), /* ... */](/*...*/) {/*...*/}

换句话说,将移动的值包装到std::shared_ptr中,如果愿意,您也可以使用std::unique_ptr 。

包装成共享指针解决了这个问题,因为共享指针(也是唯一的)允许修改其底层对象值,即使指针本身是const

不要忘记在 lambda 体内将其p作为指针取消引用,换句话说,如果您使用过p.SomeMethod(),现在您必须使用p->SomeMethod()(with->运算符)。