我需要使用initializer_list初始化一个编译时大小的类数组。我已经知道我可以使用参数包构造函数并当场对其进行初始化,但是在这种情况下,我需要使用initializer_list。我还想避免在可能的情况下动态初始化数组。这是伪代码:
template<typename Type, std::size_t Length>
class Test
{
public:
Test(const std::initializer_list<Type> args)
: m_tData(args) //<-- Doesn't work of course
{}
private:
Type m_tData[Length];
};
当然,对于非const类型,我可以做到
Test(const std::initializer_list<Type> args)
{
std::copy(args.start(), args.end(), m_tData);
}
但是如果我尝试使用像Test<const int, 3>({1, 2, 3})
这样的const类,这将不起作用。我是否被迫使用模板专门化来使内部数组实际上不是const,以便可以从构造函数主体中对其进行初始化?
我正在使用C ++ 20。我见过How do I initialize a member array with an initializer_list?,但想知道此后是否有任何变化。
答案 0 :(得分:5)
可能的解决方案:
template<typename Type, std::size_t Length>
class Test
{
public:
Test(std::initializer_list<Type> args) :
Test(args, std::make_index_sequence<Length>{})
{
assert(args.size() == Length);
}
private:
template<std::size_t... ii>
Test(std::initializer_list<Type> args, std::index_sequence<ii...>) :
m_tData{(*(args.begin() + ii))...}
{}
Type m_tData[Length];
};
有没有办法我仍然可以支持比模板化长度小的长度的initializer_list?说出类似
Test<const int, 5>({1, 2, 3})
的内容吗?
如果应该使用Type{}
初始化其余元素,则只需稍作修改即可:
Test(std::initializer_list<Type> args) :
Test(args, std::make_index_sequence<Length>{})
{
assert(args.size() <= Length);
}
template<std::size_t... ii>
Test(std::initializer_list<Type> args, std::index_sequence<ii...>) :
m_tData{(ii < args.size() ? *(args.begin() + ii) : Type{})...}
{}