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

模板类内嵌结构体成员GTest验证函数封装编译报错排查

问题

我有一个单元测试,用于验证模板类Object的内嵌结构体Values的成员valueA、valueB是否等于0。希望将验证逻辑封装到一个函数中,替代重复调用EXPECT_NE/EXPECT_EQ的操作。

原测试代码如下:

template<typename T>
struct Object
{
    struct Values
    {
        int valueA;
        int valueB;
    };
    Values values = {};
    T otherStuff;
    
    void setValues(int valueA, int valueB)
    {
        values.valueA = valueA;
        values.valueB = valueB;
    }
};

TEST(UnitTest, testA)
{
    Object<int> object;
    // do stuff that modified object's values via setValues()
    EXPECT_NE(object.values.valueA, 0);
    EXPECT_EQ(object.values.valueB, 0); 
}

尝试封装后出现编译错误:

gmock-matchers.h:2074:31: error: no matching function for call to 'testing::internal::FieldMatcher<Object<int>::Values, int>::MatchAndExplainImpl(std::integral_constant<bool, false>::type, const Object<int>&, testing::MatchResultListener*&) const'
 2074 |     return MatchAndExplainImpl(
      |            ~~~~~~~~~~~~~~~~~~~^
 2075 |         typename std::is_pointer<typename std::remove_const<T>::type>::type(),
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2076 |         value, listener);

若使用Object的外层成员变量testVar进行封装则编译正常,请问为何内嵌结构体成员会出现报错?

封装后的完整代码:

using ::testing::Eq;
using ::testing::Ne;
using ::testing::Field;
using ::testing::AllOf;

template<typename T>
struct Object
{
    int testVar;
    struct Values
    {
        int valueA;
        int valueB;
    };
    Values values = {};
    T otherStuff;
    
    void setValues(int valueA, int valueB)
    {
        values.valueA = valueA;
        values.valueB = valueB;
    }
};

template <typename T, class M1, class M2>
auto MatchesStruct(M1 m1, M2 m2)
{
    return AllOf(Field(&Object<T>::Values::valueA, m1), 
                 Field(&Object<T>::Values::valueB, m2));
}

TEST(UnitTest, testA)
{
    Object<int> object;
    // do stuff that modified object's values via setValues()
    EXPECT_THAT(object, MatchesStruct<int>(Ne(0), Eq(0)));
}

原因分析与解决方案

报错原因

当前写法中,Field(&Object<T>::Values::valueA, m1)直接传入了内嵌结构体Values的成员指针,但EXPECT_THAT的目标对象是Object<T>类型——GMock的Field匹配器要求第一个参数必须是目标对象类型的成员指针,两者类型不匹配,因此触发编译错误。

而外层成员testVar能正常编译,是因为&Object<T>::testVar是Object<T>类型的成员指针,与EXPECT_THAT的目标对象类型完全一致,匹配器可以正确解析。

修复方案

需要先通过Field匹配器从Object<T>对象中取出values成员,再嵌套使用Field匹配其内部的valueA和valueB。调整后的封装函数如下:

template <typename T, class M1, class M2>
auto MatchesStruct(M1 m1, M2 m2)
{
    return Field(&Object<T>::values, 
                 AllOf(Field(&Object<T>::Values::valueA, m1),
                       Field(&Object<T>::Values::valueB, m2)));
}

第一层Field负责从Object<T>中提取values成员,第二层通过AllOf组合两个Field匹配器,分别验证values内部的valueA和valueB,类型完全匹配后即可正常编译并执行验证逻辑。

内容的提问来源于stack exchange,提问作者xyf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 15:10:22