C/C++ 预处理器:每隔一个可变参数提取一次

C/C++ preprocessor: extract every second variadic parameter

有没有办法从 C/C++ 预处理器中的可变参数列表中提取每隔一个参数?

我想编写一个宏来通过以下方式为接口方法生成样板代码:

#define INTERFACE_FN(_NAME, _X, _Y, _N_PARAMS, ...) \
    void _NAME(__VA_ARGS__) \
    { \
        processing_function(_X, _Y, _N_PARAMS, EVERY_SECOND(__VA_ARGS__); \
    }

void processing_function(int x, int y, int count, ...)
{
    va_list params;
    va_start(params, count);
    while (count--) {
        do_something(va_arg(params, ParentClass*));
    }
    va_end(params);
    // do something else
}

将用作:

INTERFACE_FN(foo, 1, 2, 0);
INTERFACE_FN(bar, 3, 4, 1, ClassX*, x);
INTERFACE_FN(jar, 5, 6, 2, ClassY*, y, ClassZ*, z);

ClassXClassYClassZParentClass的派生词;

我正在寻找 EVERY_SECOND 宏。

这是您要求的工作示例

#define EVERY_SECOND0(...)

#define EVERY_SECOND1_(second, ...) , second
#define EVERY_SECOND1(first, ...) EVERY_SECOND1_(__VA_ARGS__)

#define EVERY_SECOND2_(second, ...) , second EVERY_SECOND1(__VA_ARGS__)
#define EVERY_SECOND2(first, ...) EVERY_SECOND2_(__VA_ARGS__)

#define EVERY_SECOND3_(second, ...) , second EVERY_SECOND2(__VA_ARGS__)
#define EVERY_SECOND3(first, ...) EVERY_SECOND3_(__VA_ARGS__)

#define EVERY_SECOND4_(second, ...) , second EVERY_SECOND3(__VA_ARGS__)
#define EVERY_SECOND4(first, ...) EVERY_SECOND4_(__VA_ARGS__)

#define EVERY_SECOND5_(second, ...) , second EVERY_SECOND4(__VA_ARGS__)
#define EVERY_SECOND5(first, ...) EVERY_SECOND5_(__VA_ARGS__)

#define COUNT_EVERY_SECOND(_1,__1,_2,__2,_3,__3,_4,__4,_5,__5,num,...) EVERY_SECOND ## num
#define EVERY_SECOND(...) COUNT_EVERY_SECOND(__VA_ARGS__,5,5,4,4,3,3,2,2,1,0)(__VA_ARGS__)


#define INTERFACE_FN(_NAME, _X, _Y, _N_PARAMS, ...) \
    void _NAME(__VA_ARGS__) \
    { \
        processing_function(_X, _Y, _N_PARAMS EVERY_SECOND(__VA_ARGS__)); \
    }

class parentClass {};
class ClassX {};
class ClassY {};
class ClassZ {};

void processing_function(int x, int y, int count, ...)
{
    va_list params;
    va_start(params, count);
    while (count--) {
        do_something(va_arg(params, ParentClass*));
    }
    va_end(params);
    // do something else
}

INTERFACE_FN(foo, 1, 2, 0);
INTERFACE_FN(bar, 3, 4, 1, ClassX*, x);
INTERFACE_FN(jar, 5, 6, 2, ClassY*, y, ClassZ*, z);

预处理器输出如下所示

class parentClass {};
class ClassX {};
class ClassY {};
class ClassZ {};

void processing_function(int x, int y, int count, ...)
{
 va_list params;
 va_start(params, count);
 while (count--) {
  do_something(va_arg(params, ParentClass*));
 }
 va_end(params);

}

void foo() { processing_function(1, 2, 0 ); };
void bar(ClassX*, x) { processing_function(3, 4, 1 , x); };
void jar(ClassY*, y, ClassZ*, z) { processing_function(5, 6, 2 , y , z); };

虽然我会给出强制性警告,但可能有更简单的方法可以在没有宏的情况下执行此操作。

如果您输入奇数个参数,末尾会有一个额外的逗号,但您的用例不应出现这种情况。这允许最多 5 对(总共 10 个参数),但我认为您可以看到如何添加更多支持的模式。由于预处理器的限制

,如果不明确定义每个参数数量,就无法做到这一点

玩得开心!

编辑:

我还想指出,这可以改进,这样您就不必指定 _N_PARAMS 并让宏为您计算,只需添加一个宏

#define COUNT_EVERY_SECOND_(_1,__1,_2,__2,_3,__3,_4,__4,_5,__5,num,...) num

并用这个

替换INTERFACE_FN的定义
#define INTERFACE_FN(_NAME, _X, _Y, ...) \
    void _NAME(__VA_ARGS__) \
    { \
        processing_function(_X, _Y, COUNT_EVERY_SECOND_(__VA_ARGS__,5,ERROR,4,4,3,3,2,2,1,0) EVERY_SECOND(__VA_ARGS__)); \
    }