c++initializer-listboilerplate

How to remove hand-indexed C++ boilerplate brace-enclose lists?


I have a derived class interface for which my base class needs to define the following three protected member arrays:

template<size_t n> class Base{
public:
    static constexpr size_t n_ = n;
};

class BaseCat: protected Base<4>{
private:
    // define arrays conveniently here, using brace notation
    double A0[] = {0,1,2,3,4,5,6,7,8,9}; // this is the desired part
    double A1[] = {13,-2};
    // ...
protected:
    // the following three lines are the boilerplate
    double* A[] = {A0,A1,A2,A3}; // this is the undesired part
    double* x[] = {x0,x1,x2,x3};
    double* b[] = {b0,b1,b2,b3};
};

// the implementation of "Derived" requires A[],x[],b[] of length n to exist.
using DerivedCat = Derived<CatBase,CatBase::n_>;

This could be code written for each of the classes BaseDog:Base<3>, BaseCat:Base<4>, BaseMouse:Base<24>, and each time I hard-code some polyhedra in A,x,b for the respective model. A derived class ProcessedBase<BaseCat,BaseCat::n_> will need the protected members A,x,b to exist of according size n.

As far as I understand, macros cannot be used because of n, which is not necessarily always of value 4.

Template functions also cannot be used because A0,A1,... are hand-written variable names, hence they would have to be hand-written in the templated assignment function in turn, and would have to be passed to it, which is as much boilerplate as writing them into brace-enclosed lists.

Finally, one could try to force a mapping of names A0 to A[i] in a base of Base, but then the convenient definition of A0 via brace-enclosed list in the upper part is impossible.

Can I get the best of both worlds, i.e. keep the desired part while avoiding the undesired part as commented in the code?


Solution

  • Would this work for you?

    template <size_t n> class Base
    {
    public:
        static constexpr size_t n_ = n;
    };
    
    class BaseCat: protected Base <4>
    {
    protected:
        double A [n_] [10] =
        {
            { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
            { 13, -2 },
            { 14, -3 },
            { 15, -4 }
        };
        // x, b, ...
    };
    

    Which is pretty much what @463035818_is_not_an_ai said.

    Note that this reserves more storage for A than is actually needed, but maybe that's not an issue for you. And it's definitely time to think about making A const (or static constexpr).