You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以最简方式使用C++的co_await运算符,实现类似C# await的效果?

实现C++协程类似C# await的最小代码量

要让C的co_await实现近似C# await的基础功能,你需要自定义一个最简化的task<T>类(以及配套的协程承诺类型)——因为C标准库并未内置这类协程返回类型,且协程函数不能直接返回void(会触发编译错误,因为void不满足协程返回类型的要求)。

以下是可运行的最小核心代码:

#include <coroutine>
#include <iostream>
#include <utility>

template<typename T>
struct task;

// 协程承诺类型,负责管理协程状态与结果
template<typename T>
struct task_promise {
    T result;
    std::coroutine_handle<> continuation;

    auto get_return_object() { return task<T>{std::coroutine_handle<task_promise>::from_promise(*this)}; }
    auto initial_suspend() { return std::suspend_always{}; }
    auto final_suspend() noexcept {
        struct awaitable {
            bool await_ready() noexcept { return false; }
            void await_suspend(std::coroutine_handle<task_promise> h) noexcept {
                h.promise().continuation.resume();
            }
            void await_resume() noexcept {}
        };
        return awaitable{};
    }
    void return_value(T value) { result = std::move(value); }
    void unhandled_exception() { std::terminate(); }
};

// 协程返回类型,支持co_await
template<typename T>
struct task {
    using promise_type = task_promise<T>;
    std::coroutine_handle<promise_type> handle;

    task(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~task() { if (handle) handle.destroy(); }

    // 禁止拷贝,允许移动
    task(const task&) = delete;
    task& operator=(const task&) = delete;
    task(task&& other) noexcept : handle(other.handle) { other.handle = nullptr; }
    task& operator=(task&& other) noexcept {
        if (this != &other) {
            if (handle) handle.destroy();
            handle = other.handle;
            other.handle = nullptr;
        }
        return *this;
    }

    // 实现co_await的核心逻辑
    bool await_ready() { return false; }
    void await_suspend(std::coroutine_handle<> h) {
        handle.promise().continuation = h;
        handle.resume();
    }
    T await_resume() { return std::move(handle.promise().result); }
};

// 针对void类型的特化
template<>
struct task_promise<void> {
    std::coroutine_handle<> continuation;

    auto get_return_object() { return task<void>{std::coroutine_handle<task_promise>::from_promise(*this)}; }
    auto initial_suspend() { return std::suspend_always{}; }
    auto final_suspend() noexcept {
        struct awaitable {
            bool await_ready() noexcept { return false; }
            void await_suspend(std::coroutine_handle<task_promise> h) noexcept {
                h.promise().continuation.resume();
            }
            void await_resume() noexcept {}
        };
        return awaitable{};
    }
    void return_void() {}
    void unhandled_exception() { std::terminate(); }
};

template<>
struct task<void> {
    using promise_type = task_promise<void>;
    std::coroutine_handle<promise_type> handle;

    task(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~task() { if (handle) handle.destroy(); }

    task(const task&) = delete;
    task& operator=(const task&) = delete;
    task(task&& other) noexcept : handle(other.handle) { other.handle = nullptr; }
    task& operator=(task&& other) noexcept {
        if (this != &other) {
            if (handle) handle.destroy();
            handle = other.handle;
            other.handle = nullptr;
        }
        return *this;
    }

    bool await_ready() { return false; }
    void await_suspend(std::coroutine_handle<> h) {
        handle.promise().continuation = h;
        handle.resume();
    }
    void await_resume() {}
};

// 示例协程函数
task<int> compute_value() {
    co_return 42;
}

task<void> print_value() {
    int val = co_await compute_value();
    std::cout << "Computed value: " << val << std::endl;
}

int main() {
    auto t = print_value();
    // 手动启动协程(因为initial_suspend是suspend_always)
    t.handle.resume();
    return 0;
}

关键部分说明

  • task_promise<T>:协程的核心管理类型,负责存储协程结果、处理挂起/恢复逻辑,定义协程的返回对象、初始/最终挂起行为。
  • task<T>:作为协程的返回类型,实现了co_await所需的三个方法(await_ready、await_suspend、await_resume),让外部代码可以通过co_await等待协程完成并获取结果。
  • void类型特化:针对不返回值的协程,提供对应的task<void>和task_promise<void>实现,避免返回void导致的编译错误。
  • 为什么不能返回void:C++协程要求返回类型必须包含嵌套的promise_type类型定义,void不满足这一要求,因此必须使用自定义的task类(哪怕是无返回值的task<void>)。

这个最小实现已经能模拟C# await的基础行为:允许协程挂起等待另一个协程完成,获取其结果后继续执行。如果需要更复杂的异步调度(比如线程池支持),可以在此基础上扩展,但核心框架就是上述代码。

内容的提问来源于stack exchange,提问作者Nikitf777

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 18:55:07