[英]How I can keep track of all the functions defined with a macro to later call them all at once?
我有以下代码通过使用宏来定义新函数
#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;
}
每次调用FUNC
都会定义一个新的 function ,比如func_0
,我现在需要做的是像这样调用 func 定义的所有函数:
int main(int, char **) {
CALL_ALL_FUNC(); // this will call func_0 and func_1
return 0;
}
是否可以将每个新 FUNC 调用的名称 append 转换为向量之类的东西,以便稍后我可以对其进行迭代? 预处理器有类似的东西吗?
好吧,你可以做一些可怕的事情,比如下面的代码(只是一个想法的概述)。 但是,您是否真的应该这样做取决于您。
static std::vector<std::function<void()>> g_vec;
class Reg
{
public:
Reg(std::function<void()> f) { g_vec.push_back(f); }
};
// insert __declspec(selectany) for your compiler and do some better function passing around, maybe C style
#define FUN(x) void v##x(); inline static Reg r##x { []{ v##x(); } }; void v##x()
FUN(a)
{
std::cout << "a\n";
}
FUN(b)
{
std::cout << "b\n";
}
int main(int argc, const char * argv[])
{
for (auto& f : g_vec)
f();
}
由于提到了 Catch2,这里是一个基于那里的宏的示例。
#include <iostream>
#include <vector>
struct Func;
std::vector<Func*> func_group;
struct Func {
Func() {
func_group.push_back(this);
}
virtual void action() = 0;
};
#define CONCAT(x, y) x##y
#define PREFIX_COUNTER(prefix, counter) CONCAT(prefix, counter)
#define UNIQUE_FUNC(id) \
struct PREFIX_COUNTER(Func_, id) : public Func {\
void action();\
} PREFIX_COUNTER(func_instance_, id);\
void PREFIX_COUNTER(Func_, id)::action()
#define FUNC() UNIQUE_FUNC(__COUNTER__)
FUNC() {
std::cout << "first func" << std::endl;
}
FUNC() {
std::cout << "second func" << std::endl;
}
int main() {
for (auto func : func_group)
func->action();
return 0;
}
FUNC
宏定义了一个新的派生 class。func->action()
)。我不完全确定你想在这里做什么,但我不认为宏是正确的方法。
__COUNTER__
每次出现时都会递增,因此您无法实际检查定义了多少个函数(因为数字会不断递增)。 同样,如果您(或库)在其他地方使用它,则没有任何方法可以告诉您创建了多少函数以及__COUNTER__
被其他东西递增了多少次。
您的问题的一个可能的替代解决方案是创建一个std::vector
of function pointers 。 您还可以将其与 lambda 表达式结合起来,并将其包装在 singleton 或 static class 中,以接近您想要定义的内容:
//DynamicFunctions.h
#include <vector>
#include <functional>
class DynamicFunctions {
public:
static void add(std::function<void()> const& function) {
_functions.push_back(function);
};
static void call(int index) {
//TODO: range checking
_functions[index]();
}
static void runAll() {
for (auto const& func : _functions) {
func();
}
};
private:
static std::vector<std::function<void()>> _functions;
};
std::vector<std::function<void()>> DynamicFunctions::_functions = std::vector<std::function<void()>>();
//main.cpp
#include <iostream>
#include "DynamicFunctions.h"
int main() {
DynamicFunctions::add([]() { std::cout << "Functions[0]" << std::endl; });
DynamicFunctions::add([]() { std::cout << "Functions[1]" << std::endl; });
DynamicFunctions::add([]() { std::cout << "hi!" << std::endl;});
DynamicFunctions::call(2);
DynamicFunctions::runAll();
return 0;
}
这样,无论何时您需要创建动态 function,您都可以调用DynamicFunctions::add
而不是使用宏。 要运行 function,而不是调用func_0
,您可以将该索引传递给DynamicFunctions::call(0)
。 这样,因为它全部存储在std::vector
中,所以当您需要调用DynamicFunctions::runAll
时,您可以轻松地遍历它们
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.