高功率C++宏-用于生成过载的循环扩展

High Powered C++ Macros - Loop Expansion for Generating Overloads

本文关键字:循环 扩展 C++ 用于 高功率      更新时间:2023-10-16

摘要:

简而言之,一对宏可以用来将一个函数定义复制N次。在第N个定义期间,指定的变量或自变量可以扩展N次。

具体地说,这个文件可以通过一些巧妙的宏以某种方式大大缩短。

我已经看到了使用#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 ) )
{
}

其中LOOP_ME是一个宏。这个想法是将任何参数或变量包装在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

代码库是肯定使用宏重载技巧,如下所述:http://efesx.com/2010/07/17/variadic-macro-to-count-number-of-arguments/。然而,我不记得这个技巧在实现中具体用于什么。

另外一个特性是,一个函数只需要编写一次。因此,不知何故,在我的例子中,func的整个定义会被复制N次,而在我的示例中,N被硬编码为3。我不记得复制有问题的函数的机制,但我猜代码库使用了这样的东西:

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 )

以下是LOOPPRINTITERATE的定义。请注意,LOOPPRINT仅在使用,运算符方面有所不同。

#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被传递给它(将不会生成任何内容),则它有效。通过制作更多形式为LOOP_NPRINT_NITERATE_N的递归宏,可以简单地扩展上限。