#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中:错误:ld返回1个退出状态
答案 0 :(得分:2)
通常,C ++中的静态数据成员需要在类外部进行定义,例如:
struct A {
static int myInt;
};
A::myInt; //doesn't even have to be initialized
常量和非易失性成员是特殊的,如in the reference所示。可以使用类体内的任何常量表达式对其进行初始化:
struct A {
static const int myInt = 1;
};
int main() {
std::cout << A::myInt;
}
但是,此规则有一个例外(来自cppreference的同一段,重点是我的):
如果为常量 [非内联(自C ++ 17起)] 静态数据成员 [或constexpr 静态数据成员(自C ++ 11起)] 是odr-used,其定义为 名称空间范围仍然是必需的,但是它不能具有初始化程序。 对于constexpr数据成员,此定义已弃用(因为 C ++ 17)。
使用过的解释如下(强调我的意思):
非正式地,如果对象的值是 read(除非它是一个 编译时间常数)或写,其地址已使用,或 参考已绑定;如果使用了引用,则使用它,并且 在编译时未知其引用对象;并且功能被使用 如果对其进行了函数调用或采用了其地址。如果 使用对象,引用或函数,其定义必须 存在于程序中的某个位置;违反通常是 链接时错误。
这正是这里发生的情况。 EXPECT_EQ
通过const T&
获取参数,即将引用绑定到该类型。而且由于引用绑定到_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
成员定义了 (您不仅不必使用它,而且实际上不应该使用它)。 / p>
如果不使用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 ++程序员都更容易理解和识别它。
作为大多数标准容器,它是高效的,并且由经验丰富的人精心编写。并且它已经被无数的程序员使用,并且经过您的测试和证明,很好。