Chameleon
Chameleon

Reputation: 2147

Template classes with template members, check instantiation

I have a C++ project (library) about template classes (different types of matrices with different containers for every type and different value_type for containers - the same for vectors etc).

Every template class has template members, because a

DenseRectangularMatrix<std::vector<long double>> //type-container-value_type

must be able (if it is 5x5) to multiplied with

DenseSymmetricMatrix<std::array<float,15>> //(5x5) type-container-value_type

My problem is compilation of instantiations. Because of many template relations it is difficult to instantiate all possible cases, not only for testing/debugging, but also to check if compiler error occurs.

Any thought on this?

Upvotes: 2

Views: 130

Answers (1)

didierc
didierc

Reputation: 14750

The C approach to such a problem would probably be to use macros and scripts to ease the generation of all the possibilities. However, we're coding in C++, so let's replace macros by templates. After all, these are fundamentally typed macros.

So my idea is to decompose your types in more elementary types, and use templates to construct them.

enum {
    RECTANGULAR,
    SYMMETRIC,
} DimKind;

enum {
    DENSE,
    PARSE
} Density;

enum {
    STD_ARRAY,
    STD_VECTOR
} ContainerType;

enum {
    FLOAT,
    DOUBLE
} CoordType;

template <CoordType CT>
struct coord_def {
};

struct coord_def<FLOAT>{
    typedef float type;
};

struct coord_def<DOUBLE> {
    typedef double type;
};


template <ContainerType Cont, CoordType Coord, int Dimension>
struct container_def {
};

template <CoordType Coord, int Dim>
struct container_def<STD_ARRAY, Coord, Dim> {
    typedef std::array<Coord,Dim> type;
    static const int dim = Dim;
    // add any other helper function needed to build the test case for that particular
    // container
};

template <CoordType Coord, int Dim>
struct container_def<STD_VECTOR, Coord, Dim> {
    typedef std::vector<Coord> type;
    static const int dim = Dim;
};

template <Density D, DimKind DK, ContainerType Cont, 
                  CoordType Coord, int XDim, int YDim>
struct TestMatrix {
};

// here specialize the above according to the parameters
// you may need to include helper function to build an instance using the template
// parameters (dimension comesto mind)

Then, you have to define what sorts of operation you wish to test. They can certainly be categorized as Matrix with Component, Matrix with Vector, Matrix with Matrix.

enum { 
    // matrix ops list
} MatrixOp;

template <MatrixOp Op, typename M1, typename M2, typename Ret>
Ret binary_op(M1 m1, M2 m2);

 // overload for specific functions

template <MatrixOp Op,
                  ContainerType Cont1, ContainerType Cont2
                   CoordType Coord1, CoordType Coord2,
                   int XDim1, int YDim1, int XDim2, int YDim2,
                   Denstity D1, Density D2,
                   DimKind K1, DimKind K2>
struct test_op {
    typedef TestMatrix<...>::type M1;
    typedef TestMatrix<...>::type M2;
    void test(M1 m1, M2 m2){
         binary_op<MatrixOp,M1,M2>(m1, m2);
     }
};

Next, there are certainly algebraic relationships between your matrices that you could encode as templates, and use for your tests.

For instance, the DenseSymmetricMatrix template's parameter seems to specify a static size container type, For such a n*n matrix, the dimension of the array must be n * (n+1) / 2. DenseRectangularMatrix on the other hand seems to have its dimensions defined at runtime. But since you have the relation on dimensions as expressed above, you can easily write two test cases as templates: one which builds two matrices with matching dimensions, and the other one with non matching dimensions.

The last step is the generation of all the possibilities. A simple script going through all the enums' values in rounds should help generate all the possible tests.

I am sure you can also use an existing unit test framework (like the boost one) with these templates to construct your tests.

Upvotes: 1

Related Questions