用于调用一系列具有相似名称的宏生成函数的宏(即 f_0、f_1、f_2、...)
Macro for calling a series of macro-generated functions with similar names (i.e. f_0, f_1, f_2, ...)
我遇到了一个很奇怪的问题,我现在不知道如何解决它。
我正在使用以下宏块生成名称相似的函数:
#define CONCAT_IMPLEMENTATION(arg1, arg2) arg1 ## arg2
#define CONCAT(arg1, arg2) CONCAT_IMPLEMENTATION(arg1, arg2)
#define UNIQUE_FUNCTION_NAME(index) CONCAT(f_, index)
#define GENERATE_FUNCTION() void UNIQUE_FUNCTION_NAME(__COUNTER__) ()
所以代码如下:
GENERATE_FUNCTION()
{
std::cout << "first function" << std::endl;
}
GENERATE_FUNCTION()
{
std::cout << "second function" << std::endl;
}
替换为:
void f_0 ()
{
std::cout << "first function" << std::endl;
}
void f_1 ()
{
std::cout << "second function" << std::endl;
}
有什么方法可以实现调用所有生成函数的宏或函数吗?
也就是说它会调用从f_0到f_N的函数,其中N 是 __COUNTER__
宏的当前值。
类似的东西:
#define RUN_ALL_GENERATED_FUNCTIONS() // ??? //
int main()
{
RUN_ALL_GENERATED_FUNCTIONS();
return 0;
}
在我看来是不可能的。你能给我一些建议吗?
这里不需要宏,只需将函数指针放入向量中,然后您就可以遍历向量依次调用每个函数。一种可能的实现方式是:
#include <vector>
#include <functional>
#include <iostream>
struct Functions
{
static std::vector<std::function<void()>> functions;
template <typename T>
static T make_function(T f)
{
functions.push_back(f);
return f;
}
static void call()
{
for (auto& f : functions)
{
f();
}
}
};
std::vector<std::function<void()>> Functions::functions;
auto f_1 = Functions::make_function([]
{
std::cout << "first function" << std::endl;
});
auto f_2 = Functions::make_function([]
{
std::cout << "second function" << std::endl;
});
int main()
{
f_1();
f_2();
Functions::call();
}
如果您确实需要,您仍然可以将 Functions::make_function
包装到一个宏中。
预处理器没有魔法。要重载,无论如何你必须枚举所有可能的情况。
#define RUN_ALL_GENERATED_FUNCTIONS_1() UNIQUE_FUNCTION_NAME(0)();
#define RUN_ALL_GENERATED_FUNCTIONS_2() RUN_ALL_GENERATED_FUNCTIONS_1()UNIQUE_FUNCTION_NAME(1)();
#define RUN_ALL_GENERATED_FUNCTIONS_3() RUN_ALL_GENERATED_FUNCTIONS_2()UNIQUE_FUNCTION_NAME(2)();
#define RUN_ALL_GENERATED_FUNCTIONS_4() RUN_ALL_GENERATED_FUNCTIONS_3()UNIQUE_FUNCTION_NAME(3)();
#define RUN_ALL_GENERATED_FUNCTIONS() do{ CONCAT(RUN_ALL_GENERATED_FUNCTIONS_, __COUNTER__)() }while(0)
int main() {
RUN_ALL_GENERATED_FUNCTIONS();
// do{ f_0();f_1(); }while(0);
}
请注意 __COUNTER__
是 non-portable,您不妨使用描述性函数名称(代码的可读性很重要,__func__
将扩展为有意义的东西)并放置指针使用 __attribute__
将这些函数添加到自定义链接器部分,然后迭代该部分以执行所有函数。这是典型的做法 - 在测试框架和内核中,使用 .init
和 .fini
等部分。
我遇到了一个很奇怪的问题,我现在不知道如何解决它。
我正在使用以下宏块生成名称相似的函数:
#define CONCAT_IMPLEMENTATION(arg1, arg2) arg1 ## arg2
#define CONCAT(arg1, arg2) CONCAT_IMPLEMENTATION(arg1, arg2)
#define UNIQUE_FUNCTION_NAME(index) CONCAT(f_, index)
#define GENERATE_FUNCTION() void UNIQUE_FUNCTION_NAME(__COUNTER__) ()
所以代码如下:
GENERATE_FUNCTION()
{
std::cout << "first function" << std::endl;
}
GENERATE_FUNCTION()
{
std::cout << "second function" << std::endl;
}
替换为:
void f_0 ()
{
std::cout << "first function" << std::endl;
}
void f_1 ()
{
std::cout << "second function" << std::endl;
}
有什么方法可以实现调用所有生成函数的宏或函数吗?
也就是说它会调用从f_0到f_N的函数,其中N 是 __COUNTER__
宏的当前值。
类似的东西:
#define RUN_ALL_GENERATED_FUNCTIONS() // ??? //
int main()
{
RUN_ALL_GENERATED_FUNCTIONS();
return 0;
}
在我看来是不可能的。你能给我一些建议吗?
这里不需要宏,只需将函数指针放入向量中,然后您就可以遍历向量依次调用每个函数。一种可能的实现方式是:
#include <vector>
#include <functional>
#include <iostream>
struct Functions
{
static std::vector<std::function<void()>> functions;
template <typename T>
static T make_function(T f)
{
functions.push_back(f);
return f;
}
static void call()
{
for (auto& f : functions)
{
f();
}
}
};
std::vector<std::function<void()>> Functions::functions;
auto f_1 = Functions::make_function([]
{
std::cout << "first function" << std::endl;
});
auto f_2 = Functions::make_function([]
{
std::cout << "second function" << std::endl;
});
int main()
{
f_1();
f_2();
Functions::call();
}
如果您确实需要,您仍然可以将 Functions::make_function
包装到一个宏中。
预处理器没有魔法。要重载,无论如何你必须枚举所有可能的情况。
#define RUN_ALL_GENERATED_FUNCTIONS_1() UNIQUE_FUNCTION_NAME(0)();
#define RUN_ALL_GENERATED_FUNCTIONS_2() RUN_ALL_GENERATED_FUNCTIONS_1()UNIQUE_FUNCTION_NAME(1)();
#define RUN_ALL_GENERATED_FUNCTIONS_3() RUN_ALL_GENERATED_FUNCTIONS_2()UNIQUE_FUNCTION_NAME(2)();
#define RUN_ALL_GENERATED_FUNCTIONS_4() RUN_ALL_GENERATED_FUNCTIONS_3()UNIQUE_FUNCTION_NAME(3)();
#define RUN_ALL_GENERATED_FUNCTIONS() do{ CONCAT(RUN_ALL_GENERATED_FUNCTIONS_, __COUNTER__)() }while(0)
int main() {
RUN_ALL_GENERATED_FUNCTIONS();
// do{ f_0();f_1(); }while(0);
}
请注意 __COUNTER__
是 non-portable,您不妨使用描述性函数名称(代码的可读性很重要,__func__
将扩展为有意义的东西)并放置指针使用 __attribute__
将这些函数添加到自定义链接器部分,然后迭代该部分以执行所有函数。这是典型的做法 - 在测试框架和内核中,使用 .init
和 .fini
等部分。