【发布时间】:2015-11-09 22:20:01
【问题描述】:
我正在使用一些日志记录宏,它们应该打印出__PRETTY_FUNCTION__ 宏提供的信息,如果需要,最多可以打印两个参数的名称和值。
我的代码的简化版本看起来像
template<typename Value1, typename Value2>
void Log(std::string const& function,
std::string const& variable_1 = "", Value1 value_1 = Value1(0),
std::string const& variable_2 = "", Value2 value_2 = Value2(0)) {
std::cout << function << " "
<< variable_1 << " " << value_1 << " "
<< variable_2 << " " << value_2 << std::endl;
}
#define LOG0() Log(__PRETTY_FUNCTION__)
#define VARIABLE(value) #value, value
#define LOG1(value) Log(__PRETTY_FUNCTION__, VARIABLE(value))
#define LOG2(value, value1) Log(__PRETTY_FUNCTION__, VARIABLE(value), VARIABLE(value1))
#define LOG(arg0, arg1, arg2, arg, ...) arg
#define CHOOSE(...) LOG(,##__VA_ARGS__, LOG2, LOG1, LOG0)
#define Debug(...) CHOOSE(__VA_ARGS__)(__VA_ARGS__)
我可以像这样使用这些宏
Debug();
int x = 0;
Debug(x);
int y = 1;
Debug(x, y);
当我用 clang 编译这段代码时,我会得到一个很好的输出,其中包含类和函数信息以及变量的名称和值。 但我也收到警告,标准兼容代码不允许有零可变参数。
warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
#define CHOOSE(...) LOG(,##__VA_ARGS__, LOG2, LOG1, LOG0)
^
warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]
Debug();
另一方面,Gcc 无法编译
error: expected primary-expression before ‘)’ token
#define LOG1(value) Log(__PRETTY_FUNCTION__, VARIABLE(value))
^
Debug();
显然,使用零可变参数是危险的。
- 有什么方法可以让我将此代码转换为符合标准的代码,而不会消除只有一个宏接受零到两个参数的便利性?
- 如果这不可能,有没有办法让 gcc 也编译这段代码?
【问题讨论】:
-
##__VA_ARGS__ 的行为取决于您的 CPP 版本。它可能就像在## 之前的逗号前添加一个空格一样简单:
LOG( , ##__VA_ARGS__,... -
另外,你的宏在 g++ 4.9.2 中对我来说是一样的,除了 g++ 在没有给出值时无法推断出值的模板类型。您是否发布了完整的示例,还是缺少某些内容?
标签: c++ gcc macros clang variadic-macros