std::future存储多态对象编译报错原因及推荐实现模式咨询
编译结果不同的根本原因
C++的模板类不同实例属于完全独立的类型,不存在天然的隐式转换关系,哪怕模板实参之间支持隐式转换,模板实例之间也不会自动继承转换规则:
std::shared_ptr<Derived>可以隐式向上转换为std::shared_ptr<Base>,但std::future<std::shared_ptr<Derived>>和std::future<std::shared_ptr<Base>>是两个无关联的类型,标准库没有为它们定义转换逻辑,因此不能直接赋值。- 你使用
std::promise的写法中,std::promise<std::shared_ptr<Base>>的set_value方法接收的参数类型是std::shared_ptr<Base>,传入std::shared_ptr<Derived>时会先完成智能指针的向上转换,再存入promise,最终get_future返回的本身就是std::future<std::shared_ptr<Base>>类型,不存在跨future类型转换,因此编译正常。 std::async的返回值类型完全由传入的可调用对象返回值推导,你使用的lambda未指定返回值类型,推导结果为std::shared_ptr<Derived>,因此std::async返回的是std::future<std::shared_ptr<Derived>>,直接赋值给目标类型的future就会触发转换报错。
存储多态对象的std::future推荐实现模式
显式指定异步函数返回值类型(最常用)
直接指定异步可调用对象的返回值为基类智能指针,让std::async直接返回目标类型的future:int main () { std::future<std::shared_ptr<Base>> f = std::async([]() -> std::shared_ptr<Base> { return std::make_shared<Derived>(); }); }手动转换future类型(适配第三方接口)
如果已经拿到了其他接口返回的派生类类型future,可以通过promise手动做类型转换:// 假设origin_f是第三方返回的std::future<std::shared_ptr<Derived>> std::promise<std::shared_ptr<Base>> p; std::future<std::shared_ptr<Base>> target_f = p.get_future(); // 异步等待原future就绪后转换类型写入新promise std::thread([p = std::move(p), origin_f = std::move(origin_f)]() mutable { p.set_value(origin_f.get()); }).detach();如果你使用C++20及以上版本,可以用
std::future::then简化转换逻辑:std::future<std::shared_ptr<Base>> f = std::async([](){ return std::make_shared<Derived>(); }).then([](std::future<std::shared_ptr<Derived>> fut) { return fut.get(); });手动使用promise管理结果
复杂异步场景下直接使用promise控制结果写入,就是你问题中给出的写法,灵活度最高,适合自定义异步执行流程的场景。
内容的提问来源于stack exchange,提问作者The Vivandiere
相关产品推荐
相关产品推荐

