我正在处理一个库,它有一个可变的宏,意思是像printf一样使用
#define PRINTF_LIKE (FORMAT, ...) //Some statement expression
由于需要PRINTF_LIKE
来评估某些内容,并且为了避免通常的if
和悬挂else
问题的宏具有多个语句,因此使用gcc's statement expressions来实现。但是,我需要使用intel编译器构建代码,这不允许destructible entities inside a statement expression。这意味着我不能写这样的代码:
PRINTF_LIKE("%s", getString().c_str());
其中getString
返回std::string
。为了解决这个问题,我有一个简单的可变参数模板包装器。
template <typename ... Rest>
int callPrintfLike(const char* const format, Rest... rest)
{
return PRINTF_LIKE(format, rest...);//warning: format string is not a string literal [-Wformat-nonliteral]
}
并像这样使用它:
callPrintfLike("%s", getString().c_str());//warning as shown in the above comment
这会绊倒clang和gcc的-Wformat-nonliteral
警告。有没有办法让我以某种方式“转发”字符串文字,只有在没有使用字符串文字调用callPrintfLike时才会触发此警告?
编辑:以下答案之一建议使用__attribute__((format))
。但是,that doesn't work因为format
属性需要可变参数函数。
答案 0 :(得分:0)
我通过关闭该函数的警告来攻击它,但提供另一个宏来调用它并通过三元运算符的死分支重新启用这些警告。
//Compiler specific pragmas to turn off the -Wformat-security and -Wformat-literal warnings go here
template <typename ... Rest>
int callPrintfLike(const char* const format, Rest... rest)
{
return PRINTF_LIKE(format, rest...);
}
//Pop diagnostic pragmas
#define NEW_PRINTF_LIKE (FORMAT, ...) (true ? callPrintfLike(FORMAT, ##__VA_ARGS__) : printf(FORMAT, ##__VA_ARGS__))
在NEW_PRINTF_LIKE
中,printf(FORMAT, ##__VA_ARGS__)
永远不会被执行。但是,仍然会启用printf
调用和非文字FORMAT
的警告以及与格式字符串不匹配的参数的编译时检查。