Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.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_Macros_Variadic Macros - Fatal编程技术网

C++ 在变量宏中获取多个变量列表的选项有哪些?

C++ 在变量宏中获取多个变量列表的选项有哪些?,c++,c,macros,variadic-macros,C++,C,Macros,Variadic Macros,我一直在尝试使用可变宏来减少我正在使用的一些SFINAE模式中的冗余代码。具体来说,我想使用可变宏生成函数定义。(这个问题与SFINAE无关)。对于我的应用程序,我想编写一个调用现有成员函数的包装函数。实际的应用程序需要我生成一个带有SFINAE专门化的模板结构,因此有一些重复性的东西,只要有一个宏负责生成结构和函数就好了。这就是动机 下面的示例省去了所有SFINAE内容,只定义了一个包含三个具有不同参数列表的静态函数(f0、f1、f2)的结构,并尝试通过全局宏生成的函数调用这些函数。你为什么要

我一直在尝试使用可变宏来减少我正在使用的一些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;
}
将变量列表用作参数3和3。请注意,参数列表和参数列表必须彼此一致(即参数列表中传递的变量最好在参数列表中声明)

这似乎适用于本例,但如果我们试图在调用的开头添加一个固定参数(例如Foo::NAME(fixedArg,ARGS)),则会出现一些问题。如果变量列表为空,####uu VA_ARGS吞下逗号的技巧似乎不适用于这种方法

所以我的问题是:

  • 虽然这种方法似乎在gcc和clang上都能正常工作,但我找不到任何类似的例子以这种方式使用多变量列表……这让我有点紧张。这是一种有效的方法吗
  • 那么在这种方法中实际发生了什么呢?函数_WRAPPER宏如何处理两个变量列表?PARAMS和ARGS宏参数只是在宏体中展开的,还是这里发生了更复杂的事情
  • 有没有办法使用##技巧来吞下前面的逗号?将##置于宏体中参数和参数值之前会导致编译错误,将##置于VA#列表中也会导致编译错误
  • 最后一种情况的示例代码为:

    #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))
    
    将##插入函数_包装器体的错误为

     error: pasting "," and "VA_LIST" does not give a valid preprocessing token
       return Foo::NAME(1,##ARGS);\
    
    将##插入VA#列表宏体的编译错误为:

    error: '##' cannot appear at either end of a macro expansion
     #define VA_LIST2(...) ##__VA_ARGS__
                         ^
    

    我相信使用GCC
    ###
    删除逗号的语法如下:
    #定义宏(X,…)扩展(X,###VA#u ARGS#)
    。它必须跟在逗号、前缀
    \uuuu VA\u ARGS\uuuu>或命名的等效项之后,而不是独立宏的一部分。请参阅。此外,根据预处理器查看它的方式,我猜
    函数包装器在
    VA\u LIST`之前展开过,因此从它的角度来看,实际上可以看到零变量参数列表。不确定是否这是一种有效的方法(因此没有给出答案),但是,它应该完全在任何现代C/C++编译器的处理能力范围内。建议阅读/#包括:我相信使用GCC
    #
    删除逗号的语法如下:
    #定义宏(X,…)扩展(X,####VA#
    。它必须跟在逗号、前缀
    \uuuu VA\u ARGS\uuuu>或命名的等效项之后,而不是独立宏的一部分。请参阅。此外,根据预处理器查看它的方式,我猜
    函数包装器在
    VA\u LIST`之前展开过,因此从它的角度来看,实际上可以看到零变量参数列表。不确定是否这是一种有效的方法(因此不会给出答案),但是,它应该完全在现代C/C++编译器的处理能力范围内。建议阅读/#包括:
    
    error: '##' cannot appear at either end of a macro expansion
     #define VA_LIST2(...) ##__VA_ARGS__
                         ^