“转发”字符串文字
我正在处理一个带有可变参数宏的库,该宏可以像printf一样使用
I am dealing with a library that has a variadic macro meant to be used like printf
#define PRINTF_LIKE (FORMAT, ...) //Some statement expression
由于 PRINTF_LIKE $ c必须使用$ c>进行评估,以避免出现常见的
if
和悬而未决的 else
问题,因为这些宏具有多条语句,它是使用 gcc语句表达式实现的。但是,我需要使用intel编译器构建代码,该编译器不允许内部可破坏的实体语句表达式。这意味着我不能编写这样的代码:
Since PRINTF_LIKE
was required to evaluate to something, and in order avoid the usual if
and dangling else
issue with macros having multiple statements, it was implemented using gcc's statement expressions. However, I need my code to build with the intel compiler, which doesn't allow destructible entities inside a statement expression. This means I can't write code like this:
PRINTF_LIKE("%s", getString().c_str());
其中 getString
返回 std :: string
。要解决此问题,我有一个简单的可变参数模板包装器。
where getString
returns an std::string
. To work around this, I have a simple variadic template wrapper.
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时才触发此警告吗?
This trips up clang and gcc's -Wformat-nonliteral
warning. Is there a way for me to somehow "forward" string-literalness and have this warning be triggered only when callPrintfLike is not called with a string literal?
EDIT:以下答案建议使用 __ attribute __((format))
。但是,由于格式$,不起作用 。 c $ c>属性需要一个可变函数。
EDIT : One of the answers below suggested using __attribute__((format))
. However, that doesn't work since the format
attribute needs a variadic function.
我通过关闭该函数的警告来绕过它,但提供了另一个警告宏来调用它,并通过三元运算符的死枝在此处重新启用这些警告。
I hacked around it by turning warnings off for the function, but providing another macro to call it through and re-enabling those warnings here through a dead-branch of the ternary operator.
//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
的警告和参数与格式不匹配的警告字符串仍将启用。
In NEW_PRINTF_LIKE
, printf(FORMAT, ##__VA_ARGS__)
will never get executed. However, the compile-time checking of the printf
call and warnings about non-literal FORMAT
and arguments not matching the format string will still be enabled.