Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 高性能C++;宏-用于生成重载的循环扩展_C++_C Preprocessor - Fatal编程技术网

C++ 高性能C++;宏-用于生成重载的循环扩展

C++ 高性能C++;宏-用于生成重载的循环扩展,c++,c-preprocessor,C++,C Preprocessor,摘要: 简而言之,一对宏可用于将函数定义复制N次。在第N个定义期间,指定的变量或参数可以扩展N次 非常具体地说,可以通过一些巧妙的宏以某种方式大幅缩短 我已经看到了使用#include指令的解决方案,我很确定#include指令是不需要的 详细信息: 我见过一个代码库,我不再有权使用一些宏创建函数重载。我想重新创建此功能,但只能记住实现的点点滴滴。其思想是一些函数重载,如下所示: void func( int a0 ) { } void func( int a0, int a1 ) { }

摘要:

简而言之,一对宏可用于将函数定义复制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 ) )
{
}
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实现的。与宏相比,这些宏的另一个好处是,您可以实际设置断点并(在运行时)调试它们。