如何防止fmt库将传入的函数指针转为布尔值打印并捕获这类bug
解决方案
方法1:开启编译器警告直接阻断
- GCC/Clang 编译时添加编译参数:
-Wall -Wextra -Wbool-conversion,会对函数指针隐式转换为bool的操作抛出警告,搭配-Werror可将警告转为编译错误,直接阻止错误代码生成。 - MSVC 编译时添加编译参数:
/W4 /we4800,其中错误编号4800对应指针类型隐式转换为bool的场景,同样会直接阻断编译。
方法2:封装安全格式化函数做静态检查
你可以自行封装一层格式化接口,用类型萃取过滤掉函数指针类型的入参:
#include <type_traits> #include <fmt/format.h> template<typename... Args> auto safe_format(fmt::format_string<Args...> fmt_str, Args&&... args) { static_assert( (!std::is_function_v<std::remove_pointer_t<std::decay_t<Args>>> && ...), "禁止传入函数指针作为格式化参数,你可能漏写了函数调用的括号" ); return fmt::format(fmt_str, std::forward<Args>(args)...); }
后续业务代码统一使用safe_format替代原生的fmt::format,只要误传函数指针就会直接编译报错,从根源上避免这类问题。
方法3:接入静态分析工具做扫描
使用Clang-Tidy、Cppcheck等C++静态分析工具:
- Clang-Tidy 开启
bugprone-implicit-bool-conversion检查项,会主动识别这类非必要的指针转bool操作 - 也可开启
cppcoreguidelines-pro-type-bool规则,强制禁止所有隐式bool转换
方法4:改造工具函数强制必须调用
如果这类返回bool的无参模板函数是你自己封装的工具,可以改造成constexpr仿函数形式,强制必须加括号调用:
template<typename T> inline constexpr auto size_is_4 = []() constexpr -> bool { return sizeof(T) == 4; };
这种场景下如果漏写括号,传入的是lambda对象,fmt默认无法格式化该类型,会直接编译报错,不会出现隐式转bool输出true的异常情况。
内容的提问来源于stack exchange,提问作者NoSenseEtAl
相关产品推荐
相关产品推荐

