Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)...} {}
like image 327
Curious Avatar asked Jul 07 '16 20:07

Curious


People also ask

Can a class have no default constructor?

No default constructor is created for a class that has any constant or reference type members.

Can we create an array of objects for a class having default constructor?

You should define it in class CheckBook constructor. Show activity on this post. The correct way to build an array of objects having no default constructor is to use the placement new syntax to separate the allocation of the array and the construction of the objects.

Is it always necessary to provide a default constructor for a class C++?

Answer: C++ Empty constructor necessity depends upon class design requirements. We know that C++ class constructor is called when we create an object of a class. If a class is not required to initialize its data member or does not contain data member, there is no need to write empty constructor explicitly.

Do classes need default constructors?

Java doesn't require a constructor when we create a class. However, it's important to know what happens under the hood when no constructors are explicitly defined. The compiler automatically provides a public no-argument constructor for any class without constructors. This is called the default constructor.


2 Answers

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

like image 186
Brian Bi Avatar answered Sep 28 '22 07:09

Brian Bi


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 }
    { }
};
like image 25
Jonathan Wakely Avatar answered Sep 28 '22 09:09

Jonathan Wakely