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

如何自动获取C++协程函数名称以实现协程追踪器?

C++协程自动获取函数名实现方案

核心思路

标准C++的std::coroutine_handle本身不携带函数名信息,但可以通过协程的promise_type间接实现自动捕获:在promise的初始化阶段(协程函数执行初期),利用编译器宏捕获当前协程函数的名字并存储,后续通过coroutine_handle获取promise对象即可拿到函数名,全程无需用户手动传递宏。

具体实现

以下是兼容GCC/Clang/MSVC等主流编译器的完整可运行示例:

1. 定义TTask与Promise类型

#include <coroutine>
#include <string>
#include <iostream>

template<typename T>
struct TTask;

// 协程Promise类型,负责存储函数名和执行结果
template<typename T>
struct TTaskPromise {
    T result_;
    std::string func_name_;

    // 生成返回对象时自动捕获当前协程函数名
    TTask<T> get_return_object() {
        // __FUNCTION__为编译器扩展,返回完整函数名(含类名若为成员函数)
        // 若需严格遵循标准C++,可替换为__func__(仅返回短函数名)
        func_name_ = __FUNCTION__;
        return TTask<T>{std::coroutine_handle<TTaskPromise>::from_promise(*this)};
    }

    std::suspend_never initial_suspend() { return {}; }
    std::suspend_never final_suspend() noexcept { return {}; }
    void return_value(T value) { result_ = value; }
    void unhandled_exception() { std::terminate(); }
};

// 协程任务类型,持有协程句柄并提供函数名获取接口
template<typename T>
struct TTask {
    using promise_type = TTaskPromise<T>;

    std::coroutine_handle<promise_type> handle_;

    explicit TTask(std::coroutine_handle<promise_type> handle) : handle_(handle) {}

    ~TTask() {
        if (handle_) handle_.destroy();
    }

    // 获取协程函数名
    [[nodiscard]] std::string get_func_name() const {
        return handle_.promise().func_name_;
    }

    // 执行协程并获取结果
    T get_result() {
        handle_.resume();
        return handle_.promise().result_;
    }
};

2. 模拟Wait协程等待器

// 模拟协程等待操作
auto Wait(double) {
    struct Awaiter {
        bool await_ready() const { return false; }
        void await_suspend(std::coroutine_handle<>) {}
        void await_resume() {}
    };
    return Awaiter{};
}

3. 测试协程与追踪逻辑

// 目标协程函数,无需手动传递任何函数名相关宏
TTask<float> CoroFunc() {
    co_await Wait(1.0);
    co_return 1.0f;
}

int main() {
    auto task = CoroFunc();
    // 输出协程函数名:CoroFunc
    std::cout << "协程启动,函数名:" << task.get_func_name() << std::endl;
    
    float result = task.get_result();
    std::cout << "协程结束,结果:" << result << std::endl;
    
    return 0;
}

关键说明

  • 编译器宏兼容性:__FUNCTION__是主流编译器均支持的扩展宏,若需严格遵循标准C++,可替换为__func__(仅返回短函数名,不含类名等前缀)。
  • 自动捕获原理:get_return_object是协程启动后第一个被调用的promise方法,此时处于协程函数的执行上下文,__FUNCTION__自然指向当前协程函数名,无需用户手动干预。
  • 扩展追踪场景:若需追踪协程的启动、恢复、结束状态,可在promise的initial_suspend、final_suspend、await_suspend等方法中添加日志逻辑,结合存储的函数名即可实现完整状态追踪。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 07:18:18