在可变参数宏中获取多个变量列表有哪些选项?

时间:2016-06-29 00:56:09

标签: c++ c macros variadic-macros

我一直在尝试使用可变参数宏来减少我正在使用的某些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技巧对这种方法不起作用。

所以我的问题是:

  1. 虽然这种方法似乎在gcc和clang上都能正常工作,但我找不到任何以这种方式使用多个变量列表的类似例子......这让我有点紧张。这是一种有效的方法吗?
  2. 那么这种方法究竟发生了什么? FUNCTION_WRAPPER宏如何处理两个变量列表? PARAMS和ARGS宏参数是否只是在宏体中展开,还是会发生更复杂的事情?
  3. 有没有办法使用##技巧来吞掉以前的逗号?将PARAMS和ARGS值之前的##放在宏体中会导致编译错误,将##放在VA_LIST中也是如此。
  4. 最后一种情况的示例代码是:

    #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__
                         ^
    

0 个答案:

没有答案