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

如何在编译期校验协程promise_type类型是否合规?

编译期检查合法的C++协程promise_type

当然可以通过自定义concept结合static_assert实现编译期检查,甚至能让未被使用的类型也触发错误。C++标准库确实没有内置的concept来验证promise_type的合法性,所以需要我们自行实现约束逻辑。

第一步:明确promise_type的核心要求

根据C++标准,一个合法的promise_type必须满足以下核心条件:

  • 提供get_return_object()方法,返回对应协程返回类型的实例
  • 提供initial_suspend()方法,返回可等待类型(需包含await_ready()、await_suspend()、await_resume())
  • 提供final_suspend() noexcept方法,返回可等待类型
  • 提供return_void()(无返回值协程)或return_value(T)(带返回值协程)方法
  • 提供unhandled_exception()方法处理未捕获的异常
  • (可选)定义handle_type为std::coroutine_handle<promise_type>(若未定义,编译器会自动推导生成)

第二步:自定义Concept实现约束

先定义一个辅助concept验证可等待类型,再实现检查promise_type的核心concept:

#include <coroutine>
#include <concepts>
#include <stdexcept>

// 验证可等待类型的辅助concept
template<typename Awaitable>
concept Awaitable = requires(Awaitable a, std::coroutine_handle<> h) {
    { a.await_ready() } -> std::convertible_to<bool>;
    a.await_suspend(h);
    a.await_resume();
};

// 验证promise_type合法性的核心concept
template<typename Promise>
concept ValidPromiseType = requires(Promise p) {
    // 检查返回对象生成方法
    { p.get_return_object() };
    // 检查初始挂起方法
    { p.initial_suspend() } -> Awaitable;
    // 检查最终挂起方法(必须noexcept)
    { p.final_suspend() noexcept } -> Awaitable;
    // 检查返回值处理方法(二选一)
    requires (requires { p.return_void(); } || requires(auto val) { p.return_value(val); });
    // 检查异常处理方法
    { p.unhandled_exception() };
    // 可选:验证handle_type类型
    typename Promise::handle_type;
    requires std::same_as<typename Promise::handle_type, std::coroutine_handle<Promise>>;
};

第三步:触发未使用类型的编译错误

如果希望即使协程返回类型未被使用,也能触发promise_type的合法性检查,有两种常用方式:

方式1:在协程返回类型内部添加static_assert

直接在结构体定义中嵌入检查,只要类型被编译就会触发验证:

// 错误示例:空promise_type会触发编译错误
struct BadCoroResult {
    struct promise_type {};

    // 编译时强制检查promise_type合法性
    static_assert(ValidPromiseType<promise_type>, 
                  "BadCoroResult::promise_type不合法:缺少协程要求的核心方法");
};

// 正确示例:符合要求的promise_type
struct GoodCoroResult {
    struct promise_type {
        GoodCoroResult get_return_object() { return {}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() { std::terminate(); }

        using handle_type = std::coroutine_handle<promise_type>;
    };

    static_assert(ValidPromiseType<promise_type>, 
                  "GoodCoroResult::promise_type不合法"); // 不会触发错误
};

方式2:用辅助模板显式实例化检查

如果不想修改原类型定义,可以用一个专门的检查模板,通过显式实例化触发验证:

template<typename CoroReturn>
struct ValidateCoroPromise {
    static_assert(ValidPromiseType<typename CoroReturn::promise_type>, 
                  "该协程返回类型的promise_type不合法");
};

// 显式实例化,即使BadCoroResult未被使用也会触发编译错误
template struct ValidateCoroPromise<BadCoroResult>;

注意事项

  • 针对带返回值的协程,可以调整concept的requires条件,强制要求return_value()方法而非return_void()
  • 可根据自身需求扩展concept的检查项(比如自定义挂起逻辑的额外要求)
  • 这种编译期检查能在代码运行前就发现promise_type的合规问题,避免运行时的未定义行为

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:47:10