如何让gtest复用libfmt的formatter打印自定义类型以减少冗余代码?
如何让Google Test复用libfmt的formatter来打印自定义类型,避免重复编写operator<<
当然可以!你不需要为每个自定义类型重复编写operator<<,可以通过通用模板+SFINAE实现一个复用已有fmt::formatter特化的全局流插入运算符,一次性解决所有类型的适配问题。
实现通用模板
利用fmt库提供的fmt::is_formattable_v类型特性,我们可以编写一个仅对拥有合法fmt::formatter特化的类型生效的通用operator<<:
#include <fmt/format.h> #include <ostream> #include <type_traits> // 通用流插入运算符:自动复用fmt的formatter template <typename T, typename = std::enable_if_t<fmt::is_formattable_v<T>>> std::ostream& operator<<(std::ostream& os, const T& value) { return os << fmt::format("{}", value); }
工作原理
fmt::is_formattable_v<T>是fmt库提供的编译期检测工具,用来判断类型T是否存在对应的fmt::formatter特化;std::enable_if_t会在检测通过时才启用这个模板,避免和已有的非模板operator<<(比如标准库类型的流运算符)冲突;- Google Test在需要打印自定义类型时,会通过ADL(参数依赖查找)找到这个通用模板,自动调用fmt的格式化逻辑生成可读输出。
注意事项
- 命名空间位置:将这个模板放在你的自定义类型所在的命名空间,或者全局命名空间,确保ADL能正常找到它;
- 版本兼容性:
fmt::is_formattable_v从fmt 7.0版本开始提供,确保你的项目使用的fmt版本满足要求; - 优先级问题:如果某个类型已经有自己的
operator<<实现,编译器会优先选择非模板的具体实现,不会影响已有代码逻辑。
这样一来,你之前定义的CpuTimes、CpuStats、CpuLimits等类型,不需要再单独编写重复的operator<<,Google Test就能直接使用你已经实现的fmt::formatter来输出可读性强的错误信息了。
内容的提问来源于stack exchange,提问作者drhookson
相关产品推荐
相关产品推荐

