Curious
Curious

Reputation: 21510

Class with std::array of objects without default constructors

So let's assume I have the following class

class NoDefaultConstructor {
    NoDefaultConstructor() = delete;
    ...
};

And I have another class which has an array of type NoDefaultConstructor and other members

class Wrapper {
    std::array<NoDefaultConstructor, 2> arr;
    ... 
};

How can I initialize the array in the constructor for Wrapper (maybe in the initializer list using an std::intializer_list)?

More specifically, is the only way I can pass on arguments to the array constructor in the initializer list for Wrapper to have a construct similar to the following? I was thinking of doing this because the size of the array might change in the future.

template <typename... Values>
Wrapper(Values&&... values) : arr{std::forward<Values>(values)...} {}

Upvotes: 11

Views: 7431

Answers (2)

Brian Bi
Brian Bi

Reputation: 119124

std::array is required to be an aggregate. Therefore it has no nontrivial constructors, but can be initialized using aggregate initialization. Note that aggregate initialization involves a braced-init-list (that is, a brace-enclosed list of initializers) but not an std::initializer_list object.

class Wrapper {
  public:
    Wrapper() : arr {MakeNoDefaultConstructor(123),
                     MakeNoDefaultConstructor(456)} {}
    //              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ braced-init-list
  private:
    std::array<NoDefaultConstructor, 2> arr;
};

EDIT A constructor with variadic arguments could be possible here like so

#include <array>
struct NoDefault {
    NoDefault() = delete;
    NoDefault(int) {}
};
struct Wrapper {
    template <typename... Args>
    Wrapper(int b_in, Args&&... args) : b{b_in}, a{args...} {}
    int b;
    std::array<NoDefault, 3> a;
};
int main() {
    std::array<NoDefault, 2> a {12, 34};
    Wrapper w {23, 12, 34, 19};
}

This of course can be further tightly constrained by adding enable_ifs

Upvotes: 8

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

How can I initialize the array in the constructor for Wrapper (maybe in the initializer list using an std::intializer_list)?

Just as you would for any other member, but use uniform initialization because std::array doesn't have any constructors.

More specifically, is the only way I can pass on arguments to the array constructor in the initializer list for Wrapper to have a construct similar to the following?

No, why would you need to use a variadic templates for a fixed number of arguments?

Just ... write the constructor, with arguments:

class Wrapper {
    std::array<NoDefaultConstructor, 2> arr;

    Wrapper(const NoDefaultConstructor& a, const NoDefaultConstructor& b)
    : arr{ a, b }
    { }
};

Upvotes: 3

Related Questions