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

GTest使用ElementsAre测试vector<reference_wrapper<T>>编译报错问题

编译失败根因分析

1. C++标准版本升级的影响

  • C11/14标准中,std::reference_wrapper没有内置的operator==重载,两个reference_wrapper实例做相等比较时,会先触发隐式类型转换为底层的T&类型,再调用T的相等运算符完成比较,因此你的代码在C11环境下可以正常编译。
  • C++17标准新增了std::reference_wrapper的内置operator==重载,逻辑为直接比较两个reference_wrapper存储的底层指针地址。且该版本的运算符重载默认不支持const修饰的reference_wrapper左操作数调用,刚好匹配你遇到的C2678错误描述。

2. GTest版本升级的影响

  • GTest 1.8.1版本的ElementsAre匹配器内部实现会自动做隐式类型转换,遇到reference_wrapper类型时会先解引用为底层值再比较,不会触发reference_wrapper自身的operator==调用。
  • GTest 1.11版本优化了匹配器的类型推导逻辑,减少了非必要的隐式转换以提升类型安全性,会直接尝试对容器中取出的const std::reference_wrapper<T>实例调用operator==,刚好触发了C++17下的运算符不兼容问题。
可行解决方案

你可以根据实际测试需求选择任意一种方案修复:

  • 方案1:使用GTest内置的Ref匹配器,专门适配reference_wrapper类型的比较:
EXPECT_THAT(vec, ElementsAre(Ref(s1), Ref(s2), Ref(s3)));
  • 方案2:显式解引用reference_wrapper后比较底层值:
EXPECT_THAT(vec, ElementsAre(
    ResultOf([](const auto& rw) { return rw.get(); }, Eq(s1)),
    ResultOf([](const auto& rw) { return rw.get(); }, Eq(s2)),
    ResultOf([](const auto& rw) { return rw.get(); }, Eq(s3))
));
  • 方案3:如果测试逻辑需要确认引用指向的是同一个对象,也可以显式转为指针比较地址:
EXPECT_THAT(vec, ElementsAre(
    ResultOf([](const auto& rw) { return &rw.get(); }, Eq(&s1)),
    ResultOf([](const auto& rw) { return &rw.get(); }, Eq(&s2)),
    ResultOf([](const auto& rw) { return &rw.get(); }, Eq(&s3))
));

内容的提问来源于stack exchange,提问作者Mr. Boy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 03:21:00