Why does std::array not have an constructor that takes a value for the array to be filled with?

泄露秘密 提交于 2019-11-27 07:43:52

std::array is, by design, an aggregate, so has no user-declared constructors.

As you say, you could use fill after default constructing. Since it's an aggregate, default construction won't zero the memory, but will leave it uninitialised (if the contained type is trivially initialisable).

Note that you can efficiently simulate this type of constructor by taking advantage of the fact that array is not zero-initialized, and has a copy constructor and do.

template <size_t N, class T>
array<T,N> make_array(const T &v) {
    array<T,N> ret;
    ret.fill(v);
    return ret;
}

auto a = make_array<20>('z');

First of all, it is not std::array<T>, it is std::array<T,N> where N is compile time constant integral expression.

Second, std::array is made aggregate by design. So it doesn't have anything which makes it non-aggregate, which is why it doesn't have constructor... and destructor, virtual functions, etc.

You may use std::index sequence for that:

namespace detail
{

    template <typename T, std::size_t...Is>
    constexpr std::array<T, sizeof...(Is)>
    make_array(const T& value, std::index_sequence<Is...>)
    {
        return {{(static_cast<void>(Is), value)...}};
    }
}

template <std::size_t N, typename T>
constexpr std::array<T, N> make_array(const T& value)
{
    return detail::make_array(value, std::make_index_sequence<N>());
}

Demo

std::make_index_sequence is C++14, but can be implemented in C++11.

static_cast<void>(Is) is to handle evil operator, that T might provide.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!