简体   繁体   中英

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

Is the absence of

std::array<T,size>::array(const T& value);

an oversight? It seems mighty useful to me, and dynamic containers (like std::vector ) do have a similar constructor.

I am fully aware of

std::array<T,size>::fill(const T& value);

but that is not a constructor, and the memory will be zeroed out first. What if I want all -1 's like this guy ?

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.

I took answer from Jarod42 and made an extension to be able to use variable amount of Constructor arguments and also added automatic indexer as a first arg:

namespace detail {
  template <typename T, std::size_t... Seq, typename... Args>
  constexpr std::array<T, sizeof...(Seq)> make_array(std::index_sequence<Seq...>, Args &... args)
  {
    return {{(static_cast<void>(Seq), T(Seq, args...))...}};
  }
}  // namespace detail

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

class myClass {
  myClass(unsigned int i, float a, std::string b, int c):... {};
}

Usage:

auto myArray = make_array<myClass, 64>(a, b, c);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM