如何测试采用 std::initializer_list 的 ctor 具有编译时已知长度?

How to test a ctor taking std::initializer_list with a compile-time known length?

本文关键字:编译 ctor 测试 何测试 initializer std list      更新时间:2023-10-16

出于测试目的,我想用一个简单的std::initializer_list调用构造函数。假设值无关紧要,长度、值和类型在编译时是已知的,例如{ 42, 42, 42,... N-times }

由于它的构造函数是私有的,我尝试了一些包扩展的运气:

template< int Count, typename ValueType, int Value, int... Values >
struct Generator
: Generator< Count-1, ValueType, Value, Value, Values... >
{};
template< typename ValueType, int Value, int... Values >
struct Generator< 0, ValueType, Value, Values... >
{
static constexpr inline std::initializer_list<ValueType>
get()
{ return { static_cast<ValueType>(Values)... }; }
};

所以Generator<3,int,10>::get()给了我{10,10,10},是的!但是我似乎有一个生命周期问题,因为initializer_list只是一个代理对象,从函数内的{..}表达式返回。测试看不到我期望的值。我忽略了什么吗?

struct A {
A(std::initializer_list<int> l)
{ for(auto i:l) std::cout << i << std::endl; }
};
int main() {
A a { Generator<3, int, 10>::get() };
return 0;
}
// prints:
// 32765
// 1762362376
// 32765

直播: https://godbolt.org/z/jYWKB3

是的,这是一个终身问题。尽管大括号中的每个值在编译时都是已知的,但initializer_list只是一个具有两个指针(或指针+大小(的代理,它们在函数完成后指向死栈内存。

我通过将被测软件的构造移动到可变参数模板中来解决它:

template< typename TestType, int Count, typename ValueType, int Value, int... Values >
struct InitListCtorTest
: InitListCtorTest< TestType, Count-1, ValueType, Value, Value, Values... >
{};
template< typename TestType, typename ValueType, int Value, int... Values >
struct InitListCtorTest< TestType, 0, ValueType, Value, Values... >
{
TestType m_testobj { static_cast<ValueType>(Values)... };
};
struct SUT {
SUT(std::initializer_list<int> l){/*...*/}
};

int main() {
InitListCtorTest<SUT,3,int,10> gen;
// Test, if gen.m_testobj has 3 elements with value 10.
return 0;
}