gpt4 book ai didi

c++ - 如何将 GCC 的 printf 格式属性与 C++11 可变参数模板一起使用?

转载 作者:IT老高 更新时间:2023-10-28 22:41:50 35 4
gpt4 key购买 nike

我有一个 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 格式属性。

我首先用 __attribute__ ((format (printf, 2, 3))) (as this 标记 log() 函数是第一个“隐藏”参数,我需要将参数索引移动一个)。这不起作用,因为如果失败并出现编译错误:

error: args to be formatted is not ‘...’

然后,我尝试将相同的属性添加到 true_log() 函数中。它编译,但实际上没有执行错误检查:我试图传递给 log() 一些无效的格式/变量组合,并且没有发出警告。也许这种检查“为时已晚”,或者换句话说,关于变量的信息已经在调用链中丢失了?

作为最后的手段,如果我用 __attribute__ ((format (printf, 2, 0))) 注释 log(),我会收到有关错误格式的警告字符串,但不会针对无效的格式/变量组合发出诊断。

总结问题:如果我使用 C++11 的可变参数模板,如何从 GCC 进行完整的格式检查?

最佳答案

我不相信你可以。我敢打赌,如果格式字符串是 literal,GCC 只会验证格式字符串。这就是为什么将 format 属性放在 true_log 上不起作用的原因 - 该函数被调用时看起来(在语法上)类似于运行时确定的字符串。将它直接放在 log 上会规避这一点,但需要 format 属性来支持可变参数模板,而你证明它不支持。

我建议你看看更多的 C++-ish 方法来进行格式化输出。例如,boost::format 有点像 printf,但会动态验证参数类型的数量和类型是否与格式字符串匹配。但是,它不使用可变参数模板,而是一个接一个地使用(通过运算符 %)提供给它的参数。

关于c++ - 如何将 GCC 的 printf 格式属性与 C++11 可变参数模板一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12573968/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com