C++ 高性能C++;宏-用于生成重载的循环扩展
摘要: 简而言之,一对宏可用于将函数定义复制N次。在第N个定义期间,指定的变量或参数可以扩展N次 非常具体地说,可以通过一些巧妙的宏以某种方式大幅缩短 我已经看到了使用C++ 高性能C++;宏-用于生成重载的循环扩展,c++,c-preprocessor,C++,C Preprocessor,摘要: 简而言之,一对宏可用于将函数定义复制N次。在第N个定义期间,指定的变量或参数可以扩展N次 非常具体地说,可以通过一些巧妙的宏以某种方式大幅缩短 我已经看到了使用#include指令的解决方案,我很确定#include指令是不需要的 详细信息: 我见过一个代码库,我不再有权使用一些宏创建函数重载。我想重新创建此功能,但只能记住实现的点点滴滴。其思想是一些函数重载,如下所示: void func( int a0 ) { } void func( int a0, int a1 ) { }
#include
指令的解决方案,我很确定#include
指令是不需要的
详细信息:
我见过一个代码库,我不再有权使用一些宏创建函数重载。我想重新创建此功能,但只能记住实现的点点滴滴。其思想是一些函数重载,如下所示:
void func( int a0 )
{
}
void func( int a0, int a1 )
{
}
void func( int a0, int a1, int a2 )
{
}
可以使用以下宏创建:
void func( LOOP_ME( int a ) )
{
}
INPUT_TEXT(
void func( LOOP_ME( int a ) ) \
{ \
} \
)
其中,LOOP_ME是一个宏。其思想是将任何参数或变量封装在要复制到循环宏中的函数中
我记得代码库中有这样的东西:
#define LOOP_ME1( x ) x##0
#define LOOP_ME2( x ) x##0, x##1
#define LOOP_ME3( x ) x##0, x##1, x##2
代码库确实使用了如下所述的宏重载技巧:。但是,我不记得这个技巧在实现中的具体用途
另一个特性是函数只需编写一次。因此,在我的示例中,func
的整个定义被复制了N次,在我的示例中,N被硬编码为3。我不记得复制所讨论的函数的机制,但我猜代码库使用了如下内容:
void func( LOOP_ME( int a ) )
{
}
INPUT_TEXT(
void func( LOOP_ME( int a ) ) \
{ \
} \
)
有没有人知道单用宏可以实现这一点?在dyp和HWalter的大量研究和帮助下,我在评论中提出了一个很好的解决方案,可以在任何一个像样的编译器上使用。下面是我们想要生成的示例:
void func( int a1 )
{
int args[] = {
a1
};
args[1 - 1] = 1;
}
void func( int a1, int a2 )
{
int args[] = {
a1,
a2
};
args[1 - 1] = 1;
args[2 - 1] = 2;
}
void func( int a1, int a2, int a3 )
{
int args[] = {
a1,
a2,
a3
};
args[1 - 1] = 1;
args[2 - 1] = 2;
args[3 - 1] = 3;
}
以下是生成上述函数的代码:
#define PARAMS( N ) \
int a##N
#define COLLECT_PARAMS( N ) \
a##N
#define ACCESS_PARAMS( N ) \
args[N - 1] = N;
#define FUNC( N ) \
void func( LOOP( PARAMS, N ) ) \
{ \
int args[] = { \
LOOP( COLLECT_PARAMS, N ) \
}; \
\
PRINT( ACCESS_PARAMS, N ) \
}
ITERATE( FUNC, 3 )
下面是循环
、打印
和迭代
的定义。请注意,循环
和打印
仅在使用,
运算符时有所不同
#define ITERATE_0( F )
#define ITERATE_1( F ) F( 1 )
#define ITERATE_2( F ) ITERATE_1( F ) F( 2 )
#define ITERATE_3( F ) ITERATE_2( F ) F( 3 )
#define ITERATE( F, N ) ITERATE_##N( F )
#define LOOP_0( F, N )
#define LOOP_1( F, N ) F( 1 )
#define LOOP_2( F, N ) LOOP_1( F, N ), F( 2 )
#define LOOP_3( F, N ) LOOP_2( F, N ), F( 3 )
#define LOOP( F, N ) LOOP_##N( F, N )
#define PRINT_0( F, N )
#define PRINT_1( F, N ) F( 1 )
#define PRINT_2( F, N ) PRINT_1( F, N ) F( 2 )
#define PRINT_3( F, N ) PRINT_2( F, N ) F( 3 )
#define PRINT( F, N ) PRINT_##N( F, N )
这是通过调用宏N次来实现的。被调用N次的宏将生成N个函数(并且可能生成函数以外的其他函数)。在每个调用内部可以运行内部循环。内部循环递归运行N次
将要生成的所有文本放在可调用宏内部的内部循环中非常重要,这样括号和逗号就不会破坏宏API,因为它们会自己分隔宏
N的上限为3,如果将0传递给N,则N有效(不会生成任何内容)。只需制作更多的递归宏即可扩展上限,这些宏的形式为
LOOP\N
、PRINT\N
和ITERATE\N
,使用宏创建了一个完整的面向对象系统。也许你可以研究一下,看看他是怎么做到的。@RobertHarvey我正在看,但也许我不清楚。这不是在C中重建C++特性,而是复制文本和扩展参数/变量名。您可以直接使用它们,也可以查看它们是如何实现的。-但同样,这使用了显式参数传递——在VS2013中似乎也是如此well@RandyGaul:对于示例代码试图实现的目标,可变模板是一个更好的解决方案。我已经为反射和脚本绑定实现了类似的系统,这些系统完全是通过variadics实现的。与宏相比,这些宏的另一个好处是,您可以实际设置断点并(在运行时)调试它们。