Search code examples
c++constructorstdarray

Init std::array in class constructor initializer list : fill values with a fixed class if default constructor is not available


I have a std::array of classes like the following one :

class Elem {
private:
    int data_;
public:
    Elem(int data) : data_(data) {}
    Elem() = delete;
};

class A {
private:
    static const int N = 3;
    std::array<Elem, N> x_;
public:
    A() : x_{ { Elem(0), Elem(0), Elem(0) } } {}
};

The code above seems to work but if 'N' is big, initialization requires too much manual effort :

A() : x_{ { Elem(0), Elem(0), Elem(0), Elem(0), Elem(0), ... } } {}

Is there a way to fill the array with a fixedElem? Take care that Elem doesn't have a default ctor. I can't use any other STL containers.

Moreover, the proposed solution requires C++11 (because of array initialization in'''A''' ctor). Is there a workaround for C++03 (i.e. using VS2013)?

Thanks

Emanuele


Solution

  • Here's a C++14 solution that uses std::index_sequence and pack expansion. It shouldn't be too difficult to port this to C++11, but not sure if it's portable to C++03 at all.

    template <std::size_t... Is, typename F>
    auto makeArrayWithHelper(std::index_sequence<Is...>, F&& f)
    {
        return std::array<decltype(f()), sizeof...(Is)>{((void)Is, f())...};
    }
    
    template <std::size_t N, typename F>
    auto makeArrayWith(F&& f)
    {
        return makeArrayWithHelper(std::make_index_sequence<N>{}, std::forward<F>(f));
    }
    
    class A {
    private:
        static const int N = 3;
        std::array<Elem, N> x_;
    public:
        A() : x_{makeArrayWith<N>([]{ return Elem(0); })} {}
    };
    

    live example on godbolt.org