1

我正在尝试编写一个返回未来的相当简单的方法。一个 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(); }

出于某种原因,我收到类型错误。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:“ ”:2 个重载对“ ”指针std::promise<std::error_code>::set_value没有合法转换this

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

4

1 回答 1

2

默认情况下,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 ->operator)。

于 2021-11-18T16:22:53.203 回答