使用initializer_list初始化数组/将initializer_list转换为参数包

时间:2019-06-04 15:36:30

标签: c++

我需要使用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?,但想知道此后是否有任何变化。

1 个答案:

答案 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];
};

https://godbolt.org/z/d8Zg3q

  

有没有办法我仍然可以支持比模板化长度小的长度的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{})...}
{}