我有一个日志功能my_log(const char* my_fmt, ...)
进行自定义日志记录。我希望my_log
遵循C printf
惯例。为了省去麻烦,我想警告用户printf()
会发出任何警告和错误。我需要的printf功能是-Wformat
警告。当然还有错误。
问题:如何在没有任何运行时开销的情况下实现此目的? (不使用编译器特定功能)。
在GCC中,我可以使用__attribute__((format()))
。
void __attribute__((format(printf,1,2))) my_log(const char* fmt, ...){ }
目前,我需要在英特尔C ++编译器(ICC)和GCC上进行编译。如果我能在ICC中实现属性检查,那就不错了。如果在编译时有一个纯C ++语言技巧来进行这样的检查,那就太棒了。
答案 0 :(得分:1)
没有可移植的方法来做到这一点。即使对于printf
系列,该语言也允许编译器假设您知道自己在做什么并编译您编写的内容,尽管如果启用它,g ++会提供有用的警告。
由于您的项目是C ++,为什么不使用C ++习语并使用boost::format
(http://www.boost.org/doc/libs/1_57_0/libs/format/doc/format.html)或IO流?然后你得到类型安全,甚至不用担心验证输入。
答案 1 :(得分:1)
正如其他答案所说,没有便携/标准的方式来实现问题所要求的。但是,英特尔C / C ++编译器(icc和icpc)与GNU函数属性 100%兼容。见Intel XE13。当我声明__attribute__((format())).
答案 2 :(得分:0)
没有可移植的方法。
您可以使用可变参数模板在运行时检查参数,但它会降低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});
}