如何跟踪宏定义的所有函数并实现批量调用?
问题:批量调用宏定义的函数并存储函数名到容器?
用户现有通过宏定义生成函数的代码:
#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; }
方案说明
- 全局容器:
func_list用来保存所有FUNC()生成的函数指针,作为批量调用的数据源。 - 自动注册:每次调用
FUNC()时,会生成一个静态的注册结构体实例。程序启动时(main函数执行前),该结构体的构造函数会把对应函数的指针插入到func_list中。 - 批量调用:
CALL_ALL_FUNC()通过遍历func_list,依次调用每个函数指针,完成批量执行。
预处理器的限制说明
预处理器仅能处理编译阶段的文本替换,无法直接操作C++的运行时容器(比如vector)。但我们可以利用静态对象在main前自动初始化的特性,让预处理器生成的代码间接完成函数指针的注册动作,达到类似将函数名存入容器的效果。
注意事项
- 确保全局容器的初始化顺序早于注册逻辑(本示例中容器定义在宏之前,满足要求),避免空指针问题。
- 如果需要支持不同签名的函数,可以修改容器类型为对应函数指针,或使用
std::function进行适配。
内容的提问来源于stack exchange,提问作者ellipticaldoor
相关产品推荐
相关产品推荐

