我正在尝试编写一个C variadic宏,用于检查是否使用一个或多个参数调用它。
我找到了一些使用宏来计算参数的解决方案,但这些解决方案要么是针对固定/有限数量的参数,要么依赖于共享相同类型的参数:
#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
计算最多10个参数,然后失败。但是我认为检查1对多个参数是一个更容易的问题,所以它可能有一个适用于任何类型和任意数量参数的解决方案。
我对此的使用是在某种debug_log
宏中:
#define debug_log(...) \
do { \
fprintf(verbose, " - %lu ", time(NULL)); \
if (VA_HAS_MANY_ARGS(__VA_ARGS__)) { \
fprintf(verbose, __VA_ARGS__); \
} else {
fprintf(verbose, "%s\n", __VA_ARGS__); \
} \
while (0)
可以调用debug_log("string here");
但也可以调用debug_log("string there %i\n", 5);
并生成:
- current_time_here string here\n
- current_time_there string there 5\n
分别
答案 0 :(得分:1)
以下是编写一个或多个宏的方法:
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(A,B,...) B
#define SHIFT_IN_ZERO , 0
#define ONE_OR_MANY_UTILITY(...) ONE_OR_MANY_UTILITY_I(__VA_ARGS__, SHIFT_IN_ZERO, X)
#define ONE_OR_MANY_UTILITY_I(A,B,...) B
#define ONE_OR_MANY(...) SECOND(ONE_OR_MANY_UTILITY(__VA_ARGS__), 1)
但请注意,这是一个相当复杂的宏系统(比VA_NARGS
更复杂),而且我不确定你在问题中的用例(我认为是问题)。
你本质上想要完成的事情似乎被误导了。您希望将各种用法折叠为单个宏debug_log
;这本身就是一种多态性。这是一个收获。但是,您特别试图使其中一种情况(使用一个参数调用debug_log)的行为与其他情况不同(为您添加一个NL)(使用多个参数调用debug_log)......这会否定任何好处你获得了。
如果你以同样的方式拼写宏,它应该做同样的事情。让我只需要记住/使用(/转换)一个宏,然后强迫我根据我传递的参数来学习(/改变)如何使用它,让我受益,这只是在取笑我。 debug_log
总是总是为我添加一个NL,或者永远不会添加一个。
最好使用两个不同的宏,因为它们会做两件不同的事情。但是,将这些宏折叠成一个总是做同样事情的宏会更好。
在这种情况下,强制NL进入可能是一个好主意;这有助于确保您的日志文件本身可用。但是,当您使用一个参数调用它时,而不是在使用多个参数调用时不添加NL,为什么不总是添加NL?:
#define debug_log(...) \
do { \
/* fprintf metadata--timestamp, file, log level, etc here */ \
fprintf(verbose, __VA_ARGS__); \
fputs("\n", verbose); \
} \
while (0)