gpt4 book ai didi

c++ - GTest 的 EXPECT_EQ 给出未定义的错误引用

转载 作者:行者123 更新时间:2023-11-27 23:44:00 26 4
gpt4 key购买 nike

#include <gtest/gtest.h>

template<typename T, size_t N>
size_t getSize(T (&arr)[N]){
return N;
}

template<int N>
struct ArrayParam {
static const int _length = N;
int _arr[N];
};

ArrayParam<3> ap1 = {{1,2,3}};
//ArrayParam<4> ap2 = {{1,2,3,4}};

class ParamTest: public ::testing::TestWithParam<ArrayParam<3>>{};

TEST_P(ParamTest, SizeTest){
ArrayParam<3> param = GetParam();

printf("\nparam._length == %d\n",param._length); //OK
printf("\nValue2 == %d\n",ArrayParam<3>::_length); //OK

//EXPECT_EQ(param._length,getSize(param._arr)); //NOT OK
//EXPECT_EQ(3,param._length); // NOT OK
EXPECT_EQ(3,sizeof(param._arr)/sizeof(int)); //OK

}

INSTANTIATE_TEST_CASE_P(ArraySize,ParamTest,testing::Values(ap1));

有人知道为什么当我尝试访问 _length 时 EXPECT_EQ 不能作为 printf 工作吗? ?

我的最终目标是为各种 ArrayParam<T> 编写单个测试实例对象,例如 ArrayParam<4> ap2 , ArrayParam<5> ap3 , 等等。

我得到的错误:

~/tests.cpp.o: 在函数中ParamTest_SizeTest_Test::TestBody()': ~/tests.cpp: undefined reference to ArrayParam<3>::_length' collect2: error: ld 返回 1 退出状态

最佳答案

解释

一般来说,C++中的静态数据成员需要在类外定义,像这样:

struct A {
static int myInt;
};
A::myInt; //doesn't even have to be initialized

Const和non-volatile成员比较特殊,可见in the reference .它们可以用类主体中的任何常量表达式进行初始化:

struct A {
static const int myInt = 1;
};

int main() {
std::cout << A::myInt;
}

但是,这条规则有一个异常(exception)(来自 cppreference 中的同一段,强调我的):

If a const [non-inline (since C++17)] static data member [or a constexpr static data member (since C++11)] is odr-used, a definition at namespace scope is still required, but it cannot have an initializer. This definition is deprecated for constexpr data members (since C++17).

odr-used 是这样解释的(强调我的):

Informally, an object is odr-used if its value is read (unless it is a compile time constant) or written, its address is taken, or a reference is bound to it; a reference is odr-used if it is used and its referent is not known at compile time; and a function is odr-used if a function call to it is made or its address is taken. If an object, a reference or a function is odr-used, its definition must exist somewhere in the program; a violation of that is usually a link-time error.

这正是这里发生的事情。 EXPECT_EQ 通过 const T& 获取参数,即绑定(bind)一个引用到这个类型。由于引用绑定(bind)到 _length,它使其成为 odr-used 并且需要类外成员定义。

odr-used 异常不适用于 printf,因为 printf(作为 C 函数)不采用引用。它属于定义的“读取(除非它是编译时常量)”部分。由于我们有一个编译时间常量,所以一切正常。

解决方案

如果您使用的是 C++17,只需将 const 更改为 constexpr 即可:

template<int N>
struct ArrayParam<N> {
static constexpr int _length = N;
int _arr[N];
};

C++17 标准为命名空间范围内的 constexpr static 成员定义已弃用(你不仅不必使用它,实际上你不应该使用它)。


如果您不使用 C++17,则必须在与该类相同的命名空间中添加此数据成员的定义:

template<int N>
struct ArrayParam<N> {
static constexpr int _length = N; //const is fine as well
int _arr[N];
};
template<int N>
constexpr int ArrayParam<N>::_length;

这将允许您将它与 GoogleTest 的 EXPECT_EQ

一起使用

作为旁注,我想推荐再次使用 std::array。它更具可读性,更容易被所有 C++ 程序员识别。
作为大多数标准容器,它是高效的,并且由经验丰富的人编写得很好。在您之前使用它的无数程序员已经过测试并证明它很好。

关于c++ - GTest 的 EXPECT_EQ 给出未定义的错误引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52205340/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com