我试图在C ++中为日志记录类创建友好的接口。本练习的最终目标是能够创建一个可以根据所使用的级别进行更改的单个定义:
MODULE_LOG(name, LOG_ALARM);
有几个级别,但我只想更改上面的定义。例如记录消息也会改为:
MODULE_LOG(name, LOG_MESSAGE, LOG_ALARM);
这个想法是代码将有一个打印定义,它将根据MODULE_LOG定义中的请求定义/取消。因此,如果未定义LOG_MESSAGE,则消息打印宏将被定义为空,否则如果它在列表中将被打印。
看到我没有使用define / undef路由,我想到了使用变量。我的想法是根据传入的级别创建一组变量。例如
#define LOG_LEVEL(lvl,val) \
static int LOG_LEVEL_##lvl = val
但是,我在C ++中使用variadic宏会遇到另一个问题。我似乎无法让宏创建多个名称(即用户传入LOG_MESSAGE和LOG_ALARM,只创建其中一个)。此外,我无法动态设置单个值。
所以我的问题是:
有没有办法使用定义来定义/取消打印宏?
可以使用variadic宏来迭代传递给它的列表并根据需要创建变量吗?
感谢。
编辑 - 无法使用提升。
答案 0 :(得分:2)
如何使用数组捕获varargs?
enum LogLevel { LOG_ALARM, LOG_MESSAGE /*, ...*/, LOG_UNDEFINED};
#ifdef LOGGING_ENABLED
#define MODULE_LOG(name, ...) \
LogLevel levels[] = { __VA_ARGS__ , LOG_UNDEFINED } \
for(int i = 0; levels[i] != LOG_UNDEFINED; i++) \
printLog(levels[i], name) // or something
#else
#define MODULE_LOG(name, ...)
#endif
答案 1 :(得分:0)
#define
。您需要的第一件事是知道宏获取了多少参数。没有直接的方法,但请看这个(取自here):
#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5,4,3,2,1)
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,N,...) N
现在您可以执行以下操作:
#define CONCAT(a,b) a##b
#define A(...) CONCAT(A,A_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
#define A_1(x) something(x)
#define A_2(x, y) something_else(x, y)
...
您必须根据要支持的最大参数数重新执行上述定义。