必须用std::promise/std::future手动构建可移动、异常安全的两阶依赖链,或封装task_then模板函数实现链式调用,或进一步抽象为支持continuation的RAII式Task包装器。

要在C++中实现多个异步任务按严格顺序逐个执行、前一个完成才触发下一个,且不依赖Boost或协程(如面向C++17及以下环境),必须绕过std::future原生缺乏.then()的限制,手动建立可移动、可衔接、异常安全的状态传递链。
用 std::promise/std::future 构建两阶显式依赖链
这是最轻量、标准库纯实现的起点,适用于确定性短链(如加载→解析→渲染)。
第一步:声明首个 promise 并获取其 future,启动第一阶段异步任务:
std::promise
第二步:声明第二个 promise,构造 lambda 捕获 【已 move 的 p1 和 p2】,确保它们在线程执行期内有效:
std::promise<:string> p2; auto f2 = p2.get_future(); std::thread([p1 = std::move(p1), p2 = std::move(p2)]() mutable { int x = p1.get_future().get(); p2.set_value(std::to_string(x * 2)); }).detach();
第三步:在主线程中消费最终结果 —— 注意 f1 和 f2 都只能调用一次 get(),否则抛 future_error: No state。
封装 task_then 模板函数实现语法糖式链式调用
避免每层都手写 thread + move + detach,把重复逻辑收口为可复用函数。
方法一:基础模板实现(支持值传递与异常传播)
template
这一步操作起来很简单,直接把文件拖进去就行。调用时写成 auto f2 = task_then(std::move(f1), [](int x) { return x * 2; }); 即可获得下一阶段 future。
方法二:支持 void 返回类型的重载(常用于无返回值的副作用任务)
template
注意:此处 f.wait() 替代 f.get(),避免对 void future 调用 get() 导致编译失败。
构建可移动、可组合的 Task 包装器
当链长超过三阶,或需支持多次 then()、错误处理、取消语义时,裸 future/promise 组合难以维护。此时应封装为 RAII 式 Task 对象。
① 定义核心结构体,持有 shared_ptr 管理状态,支持移动构造:
template
② 实现 then() 成员函数:不立即执行,只将回调压入当前 state 的 continuations 向量,并返回新 Task 实例,其 state 与原对象共享。
③ 在 run() 或外部调度器中,当 status 变为 2 或 3 时,遍历并依次调用所有 continuations —— 这是链式触发的实际执行点。
④ 所有捕获必须用值方式([x = std::move(val)])或 shared_ptr,禁止 this 捕获或引用局部变量,否则链执行中途访问已析构内存。
这一步最关键:Task 对象本身不拥有线程,它只定义“做什么”和“谁来接着做”,调度权交给外部线程池或事件循环。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











