Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

write a constexpr constructor which constructs an array of another class with default constructor deleted

I have two classes A and B, where B contains an array of A.
I will get a compiler error of this constructor of B (complains that the default constructor of A cannot be referenced), unless the default constructor of A is not deleted. What I understand about this compiling issue is that, by writing this constructor of B, due to the lack of initialization list, compiler will assume to add a default constructor of A into it, which will cause an error since it’s deleted.
How can I get rid of this error?

constexpr int data[] = {1,2,3,4,5};
constexpr size_t N = sizeof(data)/sizeof(int);

struct A { 
    A() = delete; // error in B constructor if using this
    // constexpr A() = default; // no error if using this instead
    constexpr A(int a): a_(a) {}
private:
    int a_ = 0;
};

struct B{
    constexpr B() { // error: the default constructor of A cannot be referenced
        for(size_t i = 0; i < N; i++) arr_[i] = A(data[i]);
    }
private:
    A arr_[N];
};

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

The direct solution when N is 5 is to just initialize arr_ in the member initializer list:

struct B {
    constexpr B()
        : arr_{A(data[0]), A(data[1]), A(data[2]), A(data[3]), A(data[4])} {}

private:
    A arr_[N];
};

This becomes cumbersome if you need to change N or make it into a template parameter. You can generalize the initialization by using std::array and a lambda:

C++20 and later:

#include <array>
#include <utility>

struct B {
    constexpr B()
        : arr_{[]<std::size_t... I>(std::index_sequence<I...>) {
              return std::array{A(data[I])...};
          }(std::make_index_sequence<N>())} {}

private:
    std::array<A, N> arr_;
};

In C++14 / C++17, you can’t use lambda templates so you can move that out to a helper function:

struct B {
private:
    template<std::size_t... I>
    static constexpr std::array<A, N> helper(std::index_sequence<I...>) {
        return std::array<A, N>{A(data[I])...};
    }
public:
    constexpr B()
        : arr_{helper(std::make_index_sequence<N>())} {}

private:
    std::array<A, N> arr_;
};
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading