如何使用GCC的printf格式属性与C ++ 11可变参数模板? [英] How to use GCC's printf format attribute with C++11 variadic templates?

查看:161
本文介绍了如何使用GCC的printf格式属性与C ++ 11可变参数模板?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C ++类,它是日志系统的前端。其日志功能使用C ++ 11的可变参数模板实现:

I have a C++ class that is the frontend for a logging system. Its logging function is implemented using C++11's variadic templates:

template <typename... Args>
void Frontend::log(const char *fmt, Args&&... args) {
  backend->true_log(fmt, std::forward<Args>(args)...);
}

每个日志记录后端实现自己的版本 true_log ,除其他外,使用转发的参数调用 vsnprintf 。例如:

Each logging backend implements its own version of true_log, that, among other things, uses the forwarded parameters to call vsnprintf. E.g.:

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格式属性。

Now, I want to add a static check on the log() parameters: specifically, I would like to use GCC's printf format attribute.

我开始用 log() $ c> __ attribute__((format(printf,2,3)))(这个是第一个hidden参数,移位参数索引1)。这不工作,因为如果失败并出现编译错误:

I started by tagging the log() function with __attribute__ ((format (printf, 2, 3))) (as this is the first "hidden" parameter, I need to shift parameter indices by one). This does not work, because if fails with a compilation error:

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

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

Then, I tried to add the same attribute to the true_log() function. It compiles, but no error checking is actually performed: I tried to pass to log() some invalid format/variable combinations, and no warning was issued. Maybe this kind of check is "too late", or, in other words, the information about the variable has been lost in the chain of calls?

作为最后的手段,如果我用 __ attribute__((format(printf,2,0)))注释 log()

As a last resort, if I annotated log() with __attribute__ ((format (printf, 2, 0))), I would receive warnings about wrong format strings, but no diagnostic would be issued for invalid format/variable combinations.

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

Summarizing the problem: how can I have full format checking from GCC if I use C++11's variadic templates?

推荐答案

我不相信你可以。我敢打赌,GCC只验证格式字符串,如果它是一个字面值。这就是为什么把格式属性放在 true_log 上不起作用 - 像运行时确定的字符串。直接放在 log 可以避免这种情况,但需要格式属性来支持可变参数模板, 't。

I don't believe you can. I bet that GCC only verifies the format string if it's a literal. This is why putting the format attribute on true_log doesn't work - that function is called with what looks (syntactically) like a runtime-determined string. Putting it on log directly would circumvent that, but would require format attributes to support variadic template, which you proved it doesn't.

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

I suggest that you look at more C++-ish ways to do formatted output. There is, for example, boost::format which works kind of like printf, but dynamically verifies that the number and types of the parameters types match the format string. It doesn't use variadic templates, though, but instead consumes parameters fed to it (via operator %) one-by-one.

这篇关于如何使用GCC的printf格式属性与C ++ 11可变参数模板?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆