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

如何跟踪宏定义的所有函数并实现批量调用?

问题:批量调用宏定义的函数并存储函数名到容器?

用户现有通过宏定义生成函数的代码:

#include <iostream>

#define CONCAT(x, y) x##y
#define PREFIX_COUNTER(prefix, counter) CONCAT(prefix, counter)
#define FUNC() void PREFIX_COUNTER(func_, __COUNTER__)()

FUNC() {
    std::cout << "first func" << std::endl;
}

FUNC() {
    std::cout << "second func" << std::endl;
}

int main(int, char **) {
    func_0();
    func_1();
    return 0;
}

需求是实现CALL_ALL_FUNC()宏,批量调用所有通过FUNC()定义的函数;同时想知道能否将这些函数名存入vector之类的容器,以及预处理器是否支持这类操作。


核心结论

  • 预处理器本身不支持直接将函数名存入容器,它仅负责编译阶段的文本替换,没有运行时容器的概念,但可以通过预处理器配合C++运行时逻辑间接实现类似效果。
  • 可以通过修改宏定义,在生成函数的同时自动将函数指针注册到全局容器,进而实现批量调用。

具体实现方案

修改宏定义,添加注册与批量调用逻辑

我们可以定义一个全局容器存储函数指针,在FUNC()宏中同时生成函数和注册逻辑,再通过CALL_ALL_FUNC()遍历容器完成批量调用:

#include <iostream>
#include <vector>

// 全局容器,存储无参数无返回值的函数指针
std::vector<void(*)()> func_list;

#define CONCAT(x, y) x##y
#define PREFIX_COUNTER(prefix, counter) CONCAT(prefix, counter)

// 扩展FUNC宏:生成函数 + 自动注册函数指针到容器
#define FUNC() \
void PREFIX_COUNTER(func_, __COUNTER__)(); \
struct CONCAT(registrar_, __COUNTER__) { \
    CONCAT(registrar_, __COUNTER__)() { \
        func_list.push_back(&PREFIX_COUNTER(func_, __COUNTER__ - 1)); \
    } \
} CONCAT(reg_inst_, __COUNTER__); \
void PREFIX_COUNTER(func_, __COUNTER__ - 2)()

// 实现批量调用宏
#define CALL_ALL_FUNC() \
do { \
    for (auto func : func_list) { \
        func(); \
    } \
} while(0)

// 使用FUNC定义函数
FUNC() {
    std::cout << "first func" << std::endl;
}

FUNC() {
    std::cout << "second func" << std::endl;
}

int main(int, char **) {
    CALL_ALL_FUNC(); // 自动调用所有FUNC定义的函数
    return 0;
}

方案说明

  1. 全局容器:func_list用来保存所有FUNC()生成的函数指针,作为批量调用的数据源。
  2. 自动注册:每次调用FUNC()时,会生成一个静态的注册结构体实例。程序启动时(main函数执行前),该结构体的构造函数会把对应函数的指针插入到func_list中。
  3. 批量调用:CALL_ALL_FUNC()通过遍历func_list,依次调用每个函数指针,完成批量执行。

预处理器的限制说明

预处理器仅能处理编译阶段的文本替换,无法直接操作C++的运行时容器(比如vector)。但我们可以利用静态对象在main前自动初始化的特性,让预处理器生成的代码间接完成函数指针的注册动作,达到类似将函数名存入容器的效果。

注意事项

  • 确保全局容器的初始化顺序早于注册逻辑(本示例中容器定义在宏之前,满足要求),避免空指针问题。
  • 如果需要支持不同签名的函数,可以修改容器类型为对应函数指针,或使用std::function进行适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 14:55:15