C++ 允许在宏中使用初始值设定项列表

C++ 允许在宏中使用初始值设定项列表,c++,preprocessor,C++,Preprocessor,在我正在处理的一个项目中,有一个宏记录了一个表达式。我的任务是添加向其中传递多个值的功能,并让每个值单独打印。 通过1到5个参数,我可以相对轻松地实现这一点。它甚至可以很好地传递到函数中 我现在的问题是,初始值设定项列表不再有效。该项目使用可变参数来允许在其内部进行数组初始化,如func(std::vector{0,1,0,1})。由于我已经实现了multi-arg的东西,由于逗号的缘故,它不再有效 我知道我可以做func((std::vector{0,1,0,1})),这将很好地工作,但我知道

在我正在处理的一个项目中,有一个宏记录了一个表达式。我的任务是添加向其中传递多个值的功能,并让每个值单独打印。
通过1到5个参数,我可以相对轻松地实现这一点。它甚至可以很好地传递到函数中

我现在的问题是,初始值设定项列表不再有效。该项目使用可变参数来允许在其内部进行数组初始化,如
func(std::vector{0,1,0,1})
。由于我已经实现了multi-arg的东西,由于逗号的缘故,它不再有效

我知道我可以做
func((std::vector{0,1,0,1}))
,这将很好地工作,但我知道这不会是一个好办法。有没有一种方法可以让这些在没有额外括号的情况下工作,或者在需要时添加额外括号

以下是一些相关的片段:


// Intermediate macro "chooser"
#define func_x(x, A, B, C, D, E, Func, ...) Func

// Macro to be called and used by user
// First param must be blank to allow for 0 argument function
#define func(...) func_x(, ##__VA_ARGS__, \
  func_5(__VA_ARGS__), func_4(__VA_ARGS__), func_3(__VA_ARGS__), \
  func_2(__VA_ARGS__), func_1(__VA_ARGS__), func_0())

// Macros for 1 through 5 args, calls the func_VA macro.
#define func_1(A1) func_VA(A1)
#define func_2(A1, A2) func_1(A1), func_VA(A2)
#define func_3(A1, A2, A3) func_2(A1, A2), func_VA(A3)
#define func_4(A1, A2, A3, A4) func_3(A1, A2, A3), func_VA(A4)
#define func_5(A1, A2, A3, A4, A5) func_4(A1, A2, A3, A4), func_VA(A5)

// Prints expression and type
// We use a variadic macro to support commas inside expressions (e.g.
// initializer lists):
#define func_VA(...)                                                  \
  func_macro::DebugOutput(__FILE__, __LINE__, __func__, #__VA_ARGS__) \
      .print(func_macro::type_name<decltype(__VA_ARGS__)>(), (__VA_ARGS__))


//中间宏“选择器”
#定义func_x(x,A,B,C,D,E,func,…)func
//要由用户调用和使用的宏
//第一个参数必须为空才能允许0参数函数
#定义func(…)func_x(,###uuu VA_uargs_uuu)\
func_5(uu VA_ARGS_uuu)、func_4(uu VA_ARGS_uu)、func_3(u VA_ARGS_uu)\
func_2(uu VA_ARGS_uu)、func_1(u VA_ARGS_uu)、func_0()
//对于1到5个参数的宏,调用func_VA宏。
#定义函数1(A1)函数VA(A1)
#定义func_2(A1,A2)func_1(A1),func_VA(A2)
#定义func_3(A1,A2,A3)func_2(A1,A2),func_VA(A3)
#定义函数4(A1,A2,A3,A4)函数3(A1,A2,A3),函数VA(A4)
#定义函数5(A1,A2,A3,A4,A5)函数4(A1,A2,A3,A4),函数VA(A5)
//打印表达式和类型
//我们使用可变宏来支持表达式中的逗号(例如。
//初始值设定项列表):
#定义func_VA(…)\
func_宏::调试输出(_文件_uuuuuuuuuuuuuuuuuuuuuuuuuuu行uuuuuuuuuu函数uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu\
.print(func_宏::type_name(),(uu VA_ARGS_uu))
func(std::vector{0,1,0,1});
//错误
func((std::vector{0,1,0,1}));
//工作正常,但在记录时也会打印(),因此不理想。但总比什么都没有好。
我一直在尝试在宏的某些部分插入括号来修复这个问题,但没有成功。类似于
#定义func_1(A1)func_VA((A1))
或类似功能

编辑:我取得了一些进展

如果我调用
func_1(std::vector{0,1,0,1}),那么像
#define func_1(…)func_VA(uu VA_参数)
一样声明
func_1
现在可以工作了如您所想


我制作了一个“包装器”宏,它返回
(\uu VA\u ARGS\uu)
,这允许宏与列表init一起正常工作,尽管字符串版本有额外的括号。虽然我不能让它以这样的方式工作,即您(作为用户)不必在阵列上调用wrapper(这比将brakcets放置在您自己的位置更困难)。

如果您可以将
DebugOutput::print
更改为可变模板,您可以执行以下操作:

#define func(...)                                                     \
  func_macro::DebugOutput{__FILE__, __LINE__, __func__, #__VA_ARGS__} \
      .print(__VA_ARGS__)


namespace func_macro
{

struct DebugOutput
{
    const char* filename = nullptr;
    int line = 0;
    const char* funcname = nullptr;
    const char* argsString = nullptr;

    template <typename ... Ts>
    void print(const Ts&... args) const
    {
        std::cout << filename << ":" << line << " in " << funcname << std::endl;
        std::cout << "func(" << argsString << ")\n";

        ((std::cout << typeid(args).name() << ": " << args << std::endl), ...);
    }
};

}
#定义func(…)\
func_宏::调试输出{{uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu func_uuuuuuuuuuuuuuuuuuuuuuuuu,#uuuuuu VA_uargs_uuuuuu}\
.print(_VA_ARGS__)
命名空间func_宏
{
结构调试输出
{
const char*filename=nullptr;
内线=0;
const char*funcname=nullptr;
常量char*argsString=nullptr;
模板
无效打印(常量和参数)常量
{

std::cout如果可以将
DebugOutput::print
更改为可变模板,则可以执行以下操作:

#define func(...)                                                     \
  func_macro::DebugOutput{__FILE__, __LINE__, __func__, #__VA_ARGS__} \
      .print(__VA_ARGS__)


namespace func_macro
{

struct DebugOutput
{
    const char* filename = nullptr;
    int line = 0;
    const char* funcname = nullptr;
    const char* argsString = nullptr;

    template <typename ... Ts>
    void print(const Ts&... args) const
    {
        std::cout << filename << ":" << line << " in " << funcname << std::endl;
        std::cout << "func(" << argsString << ")\n";

        ((std::cout << typeid(args).name() << ": " << args << std::endl), ...);
    }
};

}
#定义func(…)\
func_宏::调试输出{{uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu func_uuuuuuuuuuuuuuuuuuuuuuuuu,#uuuuuu VA_uargs_uuuuuu}\
.print(_VA_ARGS__)
命名空间func_宏
{
结构调试输出
{
const char*filename=nullptr;
内线=0;
const char*funcname=nullptr;
常量char*argsString=nullptr;
模板
无效打印(常量和参数)常量
{

std::cout为什么要在参数数量上重载宏?只是
#define func(…)func#u宏::DebugOutput(#文件),…)
?@KamilCuk我不完全确定这是否适用于DebugOutput类的工作方式。但也许我遗漏了什么,你能进一步告诉我吗?
#define func(…)func#宏::DebugOutput打印(func_宏::type_name(),(u__VA_参数)
我根本不知道DebugOutput是如何工作的,不是它是如何工作的,你没有展示它。@KamilCuk Yeah IK。它使用VA在内部启用逗号,比如上面的注释中所述的初始化
func\u VA
老实说,我不完全确定它是如何工作的,只是从外观上看。纵观历史,没有具体说明除了使用
而不是普通变量之外,FIC还可以使用它。
它使用VA
-在这种情况下,“VA”是什么?在类似
dbg(std::vector{0,1,0,1},std::vector{0,1,0,1})的东西上,您希望发生什么事情?
?为什么要在参数数量上重载宏?只需
#定义func(…)func_macro::DebugOutput(uu FILE_uuu,…)
?@KamilCuk我不完全确定这是否适用于DebugOutput类的工作方式。但也许我遗漏了一些东西,您能进一步启发我吗?
#定义func(…)func_macro::DebugOutput(u FILE_uu,uu行,uuu函数u,#VA_uargs)。打印(func#宏名,u(),u类型)
我根本不知道DebugOutput是如何工作的,不是它是如何工作的,你没有展示它。@KamilCuk Yeah IK。它使用VA在内部启用逗号,比如上面的注释中所述的初始化
func\u VA
老实说,我不完全确定它是如何工作的,只是从外观上看。纵观历史,没有具体说明除了使用
而不是普通变量之外,FIC也可以使用它。
它使用VA
-在这种情况下,“VA”是什么?您希望在
dbg(std::vector{0,1,0,1},st