Home > Mobile >  How can I initialize an std::array of a class without a default constructor?
How can I initialize an std::array of a class without a default constructor?

Time:02-07

Let's say I have a class without a default constructor called Foo.

If I were using an std::vector, I could do this:

std::vector<Foo> vec(100, Foo(5));

This would create a vector of 100 elements, each with value Foo(5).

How do I do the same with std::array<Foo, 100>?

I obviously do not want to list out Foo(5) explicitly 100 times in an initializer list. And yet I cannot wait till after the array is constructed to initialize it, since the lack of default constructor will produce a compiler error.

Bonus points for a solution that allows me to avoid the copy constructor as well, by supplying explicit constructor arguments similar to "placement new" or emplace functions.

CodePudding user response:

With copy constructor, something along these lines:

template <typename T, size_t... Is>
std::array<T, sizeof...(Is)> MakeArrayHelper(
    const T& val, std::index_sequence<Is...>) {
  return {(Is, val), ...};
}

template <typename T, size_t N>
std::array<T, N> MakeArray(const T& val) {
  return MakeArrayHelper<T>(val, std::make_index_sequence<N>{});
}

std::array<Foo, 100> arr = MakeArray<Foo, 100>(Foo(5));

CodePudding user response:

std::array is just a thin wrapper around a fixed array. It has no repeat-insert logic, like std::vector does. Since Foo does not have a default constructor, the only way to initialize an instance of std::array<Foo, N> is to use aggregate initialization with N number of values specified (sorry, I know you don't want to to do this), eg:

std::array<Foo, 100> arr{5, 5, 5, ...}; // N times...

Otherwise, you will have to create a byte array of sufficient size and then use placement-new in a loop, eg:

std::aligned_storage_t<sizeof(Foo), alignof(Foo)> arr[100];
for(int i = 0; i < 100;   i) {
   new (&arr[i]) Foo(5);
}
...
// use static_cast<Foo*>(&arr[index]) to access each object as needed...
...
for(int i = 0; i < 100;   i) {
    // when using placement-new, you must call each object's destructor explicitly...
    static_cast<Foo*>(&arr[i])->~Foo();
}

  •  Tags:  
  • Related