将一个char数组传递给函数模板,这样gcc就可以判断出它是一个字面量
Pass a char array to a function template such that gcc can tell it is a literal?
我正在尝试将gcc的对printf格式字符串的编译时检查与c++11的可变模板包结合起来。
我知道我可以用gcc的__attribute__((format(__printf__, ...))
装饰器装饰一个可变函数。
我知道我可以将可变变量模板包扩展为可变变量函数。例:printf(fmt, pack...);
是否有可能将两者结合起来?
在这个问题中,公认的答案指出gcc需要字量才能进行格式检查。
在下面的例子中,一个const char array
被传递给可变函数和可变函数模板。当main
中调用check
时,gcc可以告诉它是字面量,但不能从check_t
中调用
是否有任何方法将fmt
字符串传递给check_t
,使gcc将其视为字面量?
我想要实现的工作示例:
#include <iostream>
void check(const char*, ...) __attribute__((format(__printf__, 1, 2)));
void check(const char*, ...)
{
// exists only for the purposes of catching bogus format strings
}
template<typename... Ts>
void check_t(const char fmt[], Ts... ts)
{
// check the format string by expanding ts into the check function
check(fmt, ts...);
}
int main()
{
const char f[] = "foo %s";
check_t(f, 5); // compiles
check(f, 5); // fails to compile
return 0;
}
您可以在模板参数中传递c-string:
template<const char* fmt, typename... Ts>
void check_t(Ts... ts)
{
// check the format string by expanding ts into the check function
check(fmt, ts...);
}
constexpr const char f[] = "foo %s";
int main()
{
check_t<f>(5); // fails to compile
//check(f, 5); // fails to compile
return 0;
}
生活例子
如注释所述,在函数模板中不可能区分字符串字面值和字符数组,除非它是模板形参。
因此,在中利用gcc的 这种行为很容易让人想起日志框架——你既想要可变模板的类型安全,又想要格式字符串的编译时检查。__attribute__((format(__printf__, ...))
语法从中获得可变函数模板是不可能的(除非格式字符串是模板参数而不是函数参数,如@Jarod42
的回答)。
虽然这不是对特定问题的解决方案,但它是一种变通方法,可以使两者兼得。
它使用逗号操作符,特别是在链接文章中描述的例子:
i = (a, b); // discards a, stores b into i
因此宏变成这样:
#define CHECK_T(fmt, ...) ( check(fmt, __VA_ARGS__), check_t(fmt, __VA_ARGS__) )
^ ^ ^
| | |
calls variadic function `check` ---+ | |
| |
comma operator discards 1st operand -----------+ |
|
returns result of variadic function template `check_t` -------+
即使check
调用将在编译期间使格式字符串无效,我的假设是它实际上将从二进制的发布版本中编译出来,因为它是一个空函数,只留下check_t
调用进行实际的日志记录。
- 如何构造一个类型特征,可以判断一个类型的私有方法是否可以在另一个类型的构造函数中调用?
- 如何判断是否有另一个线程试图保持互斥锁?
- 编写一个函数,该函数将通过判断其每个参数的类型来自动确定其返回值
- 如何判断变量是否是一个复杂的数字C
- 我有一个包裹的矢量.我该如何判断它包含哪种类型
- 是否有函数/WinAPI 可以判断一个字符串是否以不区分大小写的语言方式以另一个字符串开头?
- 是否可以判断一个方法在编译时是否可以公开访问
- 判断一个数字是奇数还是偶数
- 判断一个键是否在一个c++无序映射中最省时的方法是什么
- 如何判断一个向量是否有一定数量的元素C++
- c++类重载:是否有可能让编译器根据模板判断使用哪一个?
- 将一个char数组传递给函数模板,这样gcc就可以判断出它是一个字面量
- 程序在c++中判断一个数字是整数还是浮点数
- c++:如何使用type_traits来判断一个类是否平凡
- 如何判断一个字符串是否包含另一个字符串
- 你能判断一个c++指针是否被销毁了吗?
- 如何判断一个函数是否被多个线程调用
- 通过c++判断一个程序是否安装在Linux中
- 如何判断一个字符串是否包含在另一个字符串中
- 我可以判断std::type_info对象是否等于另一个对象或从另一个对象派生的类吗?