我一直在尝试使用可变参数宏来减少我正在使用的某些SFINAE模式中的冗余代码。具体来说,我想使用可变参数宏生成函数定义。 (这个问题与SFINAE无关)。对于我的应用程序,我想编写一个调用现有成员函数的包装函数。实际应用程序要求我生成一个带有SFINAE特化的模板化结构,因此有一些重复的东西,只需要一个宏来处理生成结构和函数。好的,这就是动力。
以下示例省去了所有SFINAE的内容,只是使用不同的参数列表定义了具有三个静态函数(f0,f1,f2)的结构,并尝试通过全局宏生成函数调用这些函数。你为什么想做这个??你不会。但这只是为了说明我对SFINAE应用程序的问题。
#include<iostream>
struct Foo
{
static void f0()
{
std::cout<<"f0() called"<<std::endl;
}
static void f1(int a)
{
std::cout<<"f1("<<a<<") called"<<std::endl;
}
static double f2(int a, double b)
{
std::cout<<"f2("<<a<<","<<b<<") called"<<std::endl;
return a*b;
}
};
#define VA_LIST(...) __VA_ARGS__
#define FUNCTION_WRAPPER(NAME,RTYPE,PARAMS,ARGS)\
RTYPE NAME(PARAMS)\
{\
return Foo::NAME(ARGS);\
}
FUNCTION_WRAPPER(f0,void,VA_LIST(),VA_LIST())
FUNCTION_WRAPPER(f1,void,VA_LIST(int a),VA_LIST(a))
FUNCTION_WRAPPER(f2,double,VA_LIST(int a, double b), VA_LIST(a, b))
int main()
{
f0();
f1(1);
f2(1,4.2);
return 0;
}
行。因此VA_LIST(...) __VA_ARGS__
可以创建单个变量列表。电话:
FUNCTION_WRAPPER(f2,double,VA_LIST(int a, double b), VA_LIST(a, b))
将变量列表用作参数3和3.请注意,参数列表和参数列表必须彼此一致(即,参数列表中传递的变量最好在参数列表中声明。
这似乎适用于这个例子,虽然如果我们试图在调用开始时添加一个固定的参数(例如Foo :: NAME(fixedArg,ARGS)),则会出现问题。如果变量列表为空,似乎吞下逗号的## __ VA_ARGS技巧对这种方法不起作用。
所以我的问题是:
最后一种情况的示例代码是:
#define VA_LIST2(...) __VA_ARGS__
#define FUNCTION_WRAPPER2(NAME,RTYPE,PARAMS,ARGS)\
RTYPE NAME##_2(PARAMS)\
{\
return Foo::NAME(1,ARGS);\
}
FUNCTION_WRAPPER2(f2,double,VA_LIST2(double b), VA_LIST2(b))
将##插入FUNCTION_WRAPPER正文的错误是
error: pasting "," and "VA_LIST" does not give a valid preprocessing token
return Foo::NAME(1,##ARGS);\
将##插入VA_LIST宏体的编译错误是:
error: '##' cannot appear at either end of a macro expansion
#define VA_LIST2(...) ##__VA_ARGS__
^