假设我们具有以下两个功能:
void foo1(int p);
void foo2(int p, ...);
我想编写一个宏,以根据参数的数量自动扩展为适当的宏。我使用了以下肮脏的方法,但我很好奇是否有针对此问题的干净解决方案。
#define SELECT(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, NAME, ...) NAME
#define foo(...) SELECT(__VA_ARGS__, \
foo2, foo2, foo2, foo2, \
foo2, foo2, foo2, foo2, \
foo2, foo2, foo2, foo1)(__VA_ARGS__)
这种方法仅在
foo2
的参数数不超过12时有效。这是我的解决方案的一个缺点。我正在寻找一种没有此限制的方法。更新#1
真正的问题:在使用以下功能的Android NDK中,我们可以编写日志:
__android_log_print(int prio, const char *tag, const char *fmt, ...);
__android_log_write(int prio, const char *tag, const char *text);
为了简化函数名称,我定义了一个名为
LOG
的宏:#define LOG(...) __android_log_print(0, "test", __VA_ARGS__)
如果我向宏传递字符串文字,则可以,但是当我传递变量时,编译器会生成警告
-Wformat-security
。因此,我希望将具有单个参数的宏调用扩展为__android_log_write
,将其他扩展为__android_log_print
。我的日志用例:1.带/不带参数的字符串文字2.单参数变量char *
。 最佳答案
如果您的编译器支持它,则C ++ 20中的__VA_OPT__
或多或少使此过程变得简单:
#define LOG(...) LOG1(__VA_ARGS__,)(__VA_ARGS__)
#define LOG1(x, ...) LOG2##__VA_OPT__(a)
#define LOG2(x) std::cout << "n = 1: " STR(x) "\n";
#define LOG2a(x, ...) std::cout << "n > 1: " STR(x, __VA_ARGS__) "\n";
#define STR(...) STR_(__VA_ARGS__)
#define STR_(...) #__VA_ARGS__
int main()
{
LOG(1) // Prints: `n = 1: 1`
LOG(1, 2) // Prints: `n > 1: 1, 2,`
LOG(1, 2, 3) // Prints: `n > 1: 1, 2, 3,`
}