我有一个C++类,它是日志系统的前端。它的日志功能使用C++ 11的可变参数模板来实现:如何在C++ 11可变参数模板中使用GCC的printf格式属性?
template <typename... Args>
void Frontend::log(const char *fmt, Args&&... args) {
backend->true_log(fmt, std::forward<Args>(args)...);
}
每个日志后端实现自己的true_log
版本,即,除其他事项外,采用转发参数来调用vsnprintf
。例如:
void Backend::true_log(const char *fmt, ...) {
// other stuff..
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, buffer_length, fmt, ap);
va_end(ap);
// other stuff..
}
一切都很好,我很高兴。
现在,我想为log()
参数添加一个静态检查:具体来说,我想使用GCC的printf格式属性。
我开始用__attribute__ ((format (printf, 2, 3)))
标记log()
函数(因为this
是第一个“隐藏”参数,我需要将参数索引移动一个)。这是不行的,如果失败,编译错误,因为:
error: args to be formatted is not ‘...’
然后,我想同样的属性添加到true_log()
功能。它编译,但没有实际执行错误检查:我试图传递给log()
一些无效的格式/变量组合,并且没有发出警告。也许这种检查“太迟了”,换句话说,有关变量的信息在调用链中已经丢失了?
作为最后的手段,如果我注释log()
与__attribute__ ((format (printf, 2, 0)))
,我会收到有关错误格式字符串的警告,但不会针对无效的格式/变量组合发出诊断。
总结问题:如果我使用C++ 11的可变参数模板,如何从GCC进行全格式检查?
由于vsnprintf()不能处理比什么老学校...可以做什么更多,为什么要首先打扰可变参数模板呢? –
为什么当你丢弃类型信息时使用可变参数模板?只要让'true_log()'成为你真正的日志记录功能。 –
或者让'Frontend :: log'带一个变量参数... –