一种在编译时用C++根据printf格式检查参数的可移植方法
portable way of checking parameters against printf format in compile time, C++
我有一个日志函数my_log(const char* my_fmt, ...)
,用于自定义日志记录。我希望my_log
遵循printf
惯例。为了省去我的麻烦,我想警告用户printf()
会发出的任何警告和错误。我需要的printf功能是-Wformat
警告。当然还有错误。
问题:如何在没有任何运行时开销的情况下实现这一点?(不使用编译器特定功能)。
在GCC中,我可以使用__attribute__((format()))
。
void __attribute__((format(printf,1,2))) my_log(const char* fmt, ...){ }
现在,我需要在英特尔C++编译器(ICC)和GCC上进行编译。如果我能在ICC中实现属性检查,那就太好了。如果有一个纯粹的C++语言技巧可以在编译时进行这样的检查,那将是非常棒的。
没有可移植的方法。即使对于printf
系列,该语言也允许编译器假设您知道自己在做什么,并编译您所写的内容,尽管如果您启用g++,它确实会提供有用的警告。
既然你的项目是C++,为什么不使用C++习语并使用boost::format
呢(http://www.boost.org/doc/libs/1_57_0/libs/format/doc/format.html)还是IO流?然后您就可以获得类型安全性,甚至不需要担心验证输入。
正如其他答案所说,没有可移植/标准的方法来实现问题的要求。但是,英特尔C/C++编译器(icc和icpc)与GNU函数属性是100%兼容的。请参阅英特尔XE13。当我声明__attribute__((format())).
时,icpc确实会发出-Wformat警告
没有可移植的方法。
您可以在运行时使用可变模板来检查参数,但这会减慢my_log()
的速度。
此外,您可以尝试以下解决方案,但my_log()
将不遵循printf
约定。
#include <iostream>
#include <initializer_list>
#include <sstream>
class UC
{
static std::stringstream ss;
std::string str;
friend const char *Str(std::initializer_list<UC> data);
public:
template <class T> UC(T param) : str((ss.str(""), ss << param, ss.str())) {}
};
std::stringstream UC::ss;
void my_log(std::initializer_list<UC> data)
{
std::string in_str;
for (auto it = data.begin(); it != data.end(); it++)
ret += it->str;
std::cout << in_str.c_str() << 'n'; // Or whatever you want to do with your string.
}
int main()
{
my_log({"Hello", '!', 11});
}
- 0x%08lx 格式说明符在 printf 语句到 cout
- 了解 printf 格式规范中的 %03.3u
- 在没有格式说明符的情况下在c++中使用类似printf的实用程序
- 找到printf的意外错误,该格式为0.1F,用于四舍五入数字
- printf 的浮点格式标志 (%f) 仅适用于英文数字格式
- 在C 11 printf格式上寻求解释器,这些printf格式会消耗多个值
- 在CPP的COUT中等效的printf格式
- printf 格式说明符标志'0' %p,正确与否?
- 不正确的printf格式指定器编译
- 基于数据类型的printf格式
- C printf跨平台格式无警告
- 整数输出格式.什么是 printf(%.3x) 的类似物
- 从printf-复杂格式指定符模式切换到cout
- 如何将 GCC 的 printf 格式属性与 C++11 可变参数模板一起使用?
- 一种在编译时用C++根据printf格式检查参数的可移植方法
- 使用printf样式的格式设置std::字符串的内容
- Xcode 5 带有 %s 格式说明符的 LLVM printf 在调试控制台中不起作用
- printf/snprintf 格式字符 %N 有什么作用?(不是 %n)
- 在使用__attribute__((格式(printf,
- 当使用可变宏调用函数时,GCC:__attribute__((格式(printf,x,y))似乎不起作用