C++ 如何使用宏打印可变数量的参数?

C++ 如何使用宏打印可变数量的参数?,c++,c-preprocessor,variadic-macros,C++,C Preprocessor,Variadic Macros,我想定义一个参数数量可变的宏,它打印每个给定参数的名称和值 例如: 宏(x)将打印x=123 宏(x,y)将打印x,y=123666 更好的宏更具可读性 BETTER\u宏(x,y)将打印x=123,y=666 对于一个变量,我可以使用: #define MACRO(…)可能不是理想的解决方案,但: 宏本身可以接受固定数量的参数,但每个参数都可以是带括号的列表(即使它只是一个文本字符串) #定义宏(…)函数(##u VA_ARGS_uu,u VA_ARGS_u) //保留一个参数时模板递归的基本

我想定义一个参数数量可变的宏,它打印每个给定参数的名称和值

例如:

宏(x)
将打印
x=123
宏(x,y)
将打印
x,y=123666

更好的宏更具可读性

BETTER\u宏(x,y)
将打印
x=123,y=666

对于一个变量,我可以使用:


#define MACRO(…)可能不是理想的解决方案,但:

宏本身可以接受固定数量的参数,但每个参数都可以是带括号的列表(即使它只是一个文本字符串)

#定义宏(…)函数(##u VA_ARGS_uu,u VA_ARGS_u)
//保留一个参数时模板递归的基本情况
模板
void函数(常量字符*名称,Arg1&&Arg1)
{
标准::cout
1) 如何获得给定给宏的变量数

您可以使用类似的方法来计算元素:(使用硬编码限制):

2) 如何访问每个参数


这一个在C++11之前使用,没有难看的变量函数。相反,它使用难看的宏,这至少会导致编译时错误。调用语法有点不同,但不是太多。我尝试寻找类似
SEQ_ENUM
,但使用宏,却什么也找不到

首先,我们将定制打印宏:

#define PRINT_ONE(elem) BOOST_PP_STRINGIZE(elem) " = " << elem
#define PRINT_ONE_COMMA(r, data, elem) BOOST_PP_STRINGIZE(elem) " = " << elem << ", " <<
最后,我们可以迭代并打印:

#define PRINT(seq) std::cout << BOOST_PP_SEQ_FOR_EACH(PRINT_ONE_COMMA, _, REST(seq)) PRINT_ONE(LAST(seq)) << '\n';

如果您使用的是支持C++11的编译器或具有C++03非标准扩展名的编译器,这里有一个。

使用两个宏和一个模板:

#include <iostream>

struct None {};

template <typename T>
struct Log
{
    static void write(const char* name, const T& value) {
        std::clog << name << " = " << value << '\n';
    }
};

template<>
struct Log<None>
{
    static void write(const char*, const None&) {}
};

#define LOG_VALUE_DETAIL(A, B, C, D, E, ...) do { \
    Log<decltype(A)>::write(#A, A); \
    Log<decltype(B)>::write(#B, B); \
    Log<decltype(C)>::write(#C, C); \
    Log<decltype(D)>::write(#D, D); \
    Log<decltype(E)>::write(#E, E); \
} while(0)

#define LOG_VALUE(...) LOG_VALUE_DETAIL(__VA_ARGS__, None(), None(), None(), None(), None())

inline int f() { return 3; }

int main()
{

    int a = 0;
    int b = 1;
    int c = 2;
    LOG_VALUE(a, b, c, f());
    return 0;
}
#包括
结构无{};
模板
结构日志
{
静态无效写入(常量字符*名称、常量T和值){

std::clog相关:顺便说一句,Boost已经用
Boost\u PP\u VARIADIC\u SIZE
完成了多达…256?的操作。我尝试了与预期最接近的解决方案。当我将宏应用于两个以上的参数时,我注意到一个问题。
宏(a、b、c)
打印出
a=1=2,b,c=3
而不是
a=1,b=2,c=3
。我还不知道如何修复它。无论如何,感谢帮助我的人。这个社区很棒。:-)倒数第二行。替换
comma
comma+1
@captain\u flammy:对不起,我用了一种更好的方式修复了它:在
名字中添加1s
在调用strchr
的过程中。我想这会让它一直工作。很好,除了你糟糕的函数命名。还会在其中抛出一些通用引用,是吗?@LightnessRacesinOrbit:我命名函数函数是因为OP命名了宏宏。我总是尝试匹配本地约定!;-)至于通用引用ces,我已经添加了它们(希望正确)。
/* args */
#define ARG(N, ...) ARG_##N(__VA_ARGS__)

#define ARG_1(a, ...) a
#define ARG_2(a, b,...) b
#define ARG_3(a, b, c, ...) c
#define ARG_4(a, b, c, d, ...) d
#define ARG_5(a, b, c, d, e, ...) e
#define ARG_6(a, b, c, d, e, f, ...) f
#define ARG_7(a, b, c, d, e, f, g, ...) g
#define ARG_8(a, b, c, d, e, f, g, h, ...) h
#define PRINT_ONE(elem) BOOST_PP_STRINGIZE(elem) " = " << elem
#define PRINT_ONE_COMMA(r, data, elem) BOOST_PP_STRINGIZE(elem) " = " << elem << ", " <<
#define LAST(seq) BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq)), seq)
#define REST(seq) BOOST_PP_SEQ_SUBSEQ(seq, 0, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq)))
#define PRINT(seq) std::cout << BOOST_PP_SEQ_FOR_EACH(PRINT_ONE_COMMA, _, REST(seq)) PRINT_ONE(LAST(seq)) << '\n';
PRINT((var1)(var2)(var3)) // var1 = 5, var2 = 3, var3 = 7
#include <iostream>

struct None {};

template <typename T>
struct Log
{
    static void write(const char* name, const T& value) {
        std::clog << name << " = " << value << '\n';
    }
};

template<>
struct Log<None>
{
    static void write(const char*, const None&) {}
};

#define LOG_VALUE_DETAIL(A, B, C, D, E, ...) do { \
    Log<decltype(A)>::write(#A, A); \
    Log<decltype(B)>::write(#B, B); \
    Log<decltype(C)>::write(#C, C); \
    Log<decltype(D)>::write(#D, D); \
    Log<decltype(E)>::write(#E, E); \
} while(0)

#define LOG_VALUE(...) LOG_VALUE_DETAIL(__VA_ARGS__, None(), None(), None(), None(), None())

inline int f() { return 3; }

int main()
{

    int a = 0;
    int b = 1;
    int c = 2;
    LOG_VALUE(a, b, c, f());
    return 0;
}