我有一个 C++ 类,它是日志系统的前端。它的日志功能是使用 C++11 的可变参数模板实现的:
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 格式属性。
我首先使用标记log()
函数__attribute__ ((format (printf, 2, 3)))
(与this
第一个“隐藏”参数一样,我需要将参数索引移动一个)。这不起作用,因为如果失败并出现编译错误:
error: args to be formatted is not ‘...’
然后,我尝试将相同的属性添加到true_log()
函数中。它编译,但实际上没有执行错误检查:我试图传递给log()
一些无效的格式/变量组合,并且没有发出警告。也许这种检查“为时已晚”,或者换句话说,关于变量的信息已经在调用链中丢失了?
作为最后的手段,如果我log()
用注释__attribute__ ((format (printf, 2, 0)))
,我会收到有关错误格式字符串的警告,但不会针对无效的格式/变量组合发出诊断。
总结问题:如果我使用 C++11 的可变参数模板,如何从 GCC 进行完整的格式检查?