You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 06:09:25