假设我们具有以下两个功能:

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,`
}

08-16 19:59