为什么编译器不识别我的类型参数化测试夹具类的成员?

Ziv*_*Ziv 6 googletest

我正在使用gtest编写一个类型参数化的测试夹具,not declared in this scope当我尝试使用fixture类中的成员时,我看到了编译器错误.

当我没有使用类型参数化夹具时,我可以很好地访问类成员.当我正在使用一个类型参数化夹具,我可以使用this->(member name)访问该成员.但为什么我不能明确使用成员名称?有没有办法可以避免乱丢我的测试代码this->


这是一个微不足道的再现:

Test_Sanity.h:

#include "gtest/gtest.h"

/* Using a member in a simple, non-paramed fixture: */
class SimpleFixture : public ::testing::Test {
protected:
    int N;
};

TEST_F(SimpleFixture, FooTest) {
    N=6;
    ASSERT_LE(0,N);
}

/* Using a member in a type-parameterized fixture: */    
template <typename PARAM_T>
class TypeParamFixture : public ::testing::Test {
protected:
    int N;
};
TYPED_TEST_CASE_P(TypeParamFixture); 

TYPED_TEST_P(TypeParamFixture, FooTest) {
    N=6; /* COMPILE-ERROR: ‘N’ was not declared in this scope */
    ASSERT_LE(0,N);
}

/* As above, but using this->N */        
TYPED_TEST_P(TypeParamFixture, FooTestUsingThisPtr) {
    this->N=6; /* No compilation error */
    ASSERT_LE(0,this->N);
}

/* Registration and instantiation of type-paramed tests */
REGISTER_TYPED_TEST_CASE_P(TypeParamFixture, FooTest, FooTestUsingThisPtr);

struct StructA {
    int myInt;
    double myDouble;
};

struct StructB {
    char myCharArr[42];
};

typedef ::testing::Types<StructA, StructB> MyTypes;
INSTANTIATE_TYPED_TEST_CASE_P(Sanity, TypeParamFixture, MyTypes );
Run Code Online (Sandbox Code Playgroud)

我使用样板gtest main编译上面的内容,并且仅为使用Nin 而获得编译错误TypeParamFixture/FooTest.

Mik*_*han 7

预处理后,您的类型参数化测试:

TYPED_TEST_P(TypeParamFixture, FooTest) {
    N=6; /* COMPILE-ERROR: ‘N’ was not declared in this scope */
    ASSERT_LE(0,N);
}
Run Code Online (Sandbox Code Playgroud)

变成:

namespace gtest_case_TypeParamFixture_ {

template <typename gtest_TypeParam_> 
class FooTest : public TypeParamFixture<gtest_TypeParam_> 
{ 
    private: 
    typedef TypeParamFixture<gtest_TypeParam_> TestFixture; 
    typedef gtest_TypeParam_ TypeParam; virtual void TestBody(); 
}; 

static bool gtest_FooTest_defined_ __attribute__ ((unused)) = 
    gtest_typed_test_case_p_state_TypeParamFixture_.AddTestName(
        "gtest.cpp", 22, "TypeParamFixture", "FooTest");

} 

template <typename gtest_TypeParam_> 
void gtest_case_TypeParamFixture_::FooTest<gtest_TypeParam_>::TestBody()
{
    N=6; //<- Won't compile
    switch (0) case 0: default: 
        if (const ::testing::AssertionResult gtest_ar = 
            (::testing::internal::CmpHelperLE("0", "N", 0, N))) ; 
        else return ::testing::internal::AssertHelper(
                                                ::testing::TestPartResult::kFatalFailure, 
                                                "gtest.cpp", 
                                                24, 
                                                gtest_ar.failure_message()
                                            ) = ::testing::Message();
}
Run Code Online (Sandbox Code Playgroud)

关键是关键是你的类型参数化测试成为一个继承你的类型参数化测试夹具的类模板.

从这个角度来看,以下非常简单的例子说明了这个问题:

template<typename T>
struct my_base
{
    my_base() : N(0){}
    int N;
    int bar() const {
        return N; //<- This will compile
    }
};

template<typename T>
struct my_derived : my_base<T>
{
    int foo() {
        // return N; // <- This will not compile 
        return this->N; //<- This will compile
    }
};

int main()
{
    my_derived<int> d;
    return d.foo() + d.bar();
}
Run Code Online (Sandbox Code Playgroud)

经验教训是,在从类模板派生的类模板的实现中,必须通过this指针引用基本模板的成员.这只是关于C++模板机制的一个不方便的事实.


Ziv*_*Ziv 5

它似乎并不直接在文档中,但在演示类型参数化测试的示例中,我发现了以下评论:

  // Since we are in the template world, C++ requires explicitly
  // writing 'this->' when referring to members of the fixture class.
  // This is something you have to learn to live with.
Run Code Online (Sandbox Code Playgroud)

所以这里似乎没有解决方法。唉。