Google Test断言失败时如何美化打印GLM数学库对象值
GoogleTest 自定义GLM类型打印不生效问题解决
问题复现
按照GoogleTest自定义打印的指南,为自定义类型重载PrintTo函数可以正常工作:
namespace my_ns { struct A { A(uint32_t a_, uint32_t b_) : a(a_), b(b_) {} uint32_t a = 0, b = 0; bool operator==(const A &rhs) const { return a == rhs.a && b == rhs.b; } }; void PrintTo(const test::A &value, std::ostream *out) { *out << value.a << " - " << value.b; } } TEST(PrettyTest, Test) { EXPECT_EQ(my_ns::A(10, 20), my_ns::A(20, 25)); }
断言失败输出符合预期:
error: Expected equality of these values: my_ns::A(10, 20) Which is: 10 - 20 my_ns::A(20, 25) Which is: 20 - 25
但使用完全相同的方式为GLM库的vec3类型重载PrintTo时,自定义逻辑始终不触发,断言失败只输出默认的二进制内存内容:
namespace glm { void PrintTo(const vec3 &value, std::ostream *out) { *out << to_string(value); } } // namespace glm TEST_F(PrettyTest, GlmTest) { EXPECT_EQ(glm::vec3(1.0f), glm::vec3(2.0f)); }
异常输出如下:
error: Expected equality of these values: glm::vec3(1.0f) Which is: 12-byte object <00-00 80-3F 00-00 80-3F 00-00 80-3F> glm::vec3(2.0f) Which is: 12-byte object <00-00 00-40 00-00 00-40 00-00 00-40>
调整命名空间位置等常规方式均无法解决该问题。
根本原因
GLM的vec3不是独立定义的非模板结构体,而是模板类型glm::vec<3, float, defaultp>的类型别名。C++的参数依赖查找(ADL)和GoogleTest的重载匹配规则,针对模板别名的场景不会优先匹配你在glm命名空间下定义的非模板PrintTo重载,最终回退到GoogleTest内置的通用字节打印逻辑。
修复方法
将PrintTo重载定义在全局命名空间,不要放在glm命名空间内即可触发匹配。单vec3类型的最简实现:
// 全局命名空间下定义 void PrintTo(const glm::vec3& value, std::ostream* out) { *out << glm::to_string(value); }
如果需要兼容所有GLM向量/矩阵类型,可以直接定义模板版本的重载,自动匹配所有GLM向量实例:
#include <glm/glm.hpp> #include <glm/gtx/string_cast.hpp> template<glm::length_t L, typename T, glm::qualifier Q> void PrintTo(const glm::vec<L, T, Q>& value, std::ostream* out) { *out << glm::to_string(value); }
重新编译运行测试,断言失败时就会输出格式化后的可读内容,不再显示二进制内存块。
内容的提问来源于stack exchange,提问作者Gasim
相关产品推荐
相关产品推荐

