Подходът на C към подобен проблем вероятно би бил да се използват макроси и скриптове, за да се улесни генерирането на всички възможности. Ние обаче кодираме на C++, така че нека заменим макросите с шаблони. В крайна сметка това са фундаментално въведени макроси.
Така че моята идея е да разложа вашите типове на по-елементарни типове и да използвам шаблони, за да ги конструирам.
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)
След това трябва да определите какви видове операции искате да тествате. Те със сигурност могат да бъдат категоризирани като матрица с компонент, матрица с вектор, матрица с матрица.
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);
}
};
След това със сигурност има алгебрични връзки между вашите матрици, които можете да кодирате като шаблони и да използвате за вашите тестове.
Например параметърът на шаблона DenseSymmetricMatrix
изглежда указва тип контейнер със статичен размер. За такава n*n матрица размерът на масива трябва да бъде n * (n+1) / 2. DenseRectangularMatrix
от друга страна изглежда има своите размери дефинирани по време на изпълнение. Но тъй като имате връзката на измеренията, както е изразено по-горе, можете лесно да напишете два тестови случая като шаблони: единият, който изгражда две матрици със съвпадащи размери, а другият с несъвпадащи размери.
Последната стъпка е генерирането на всички възможности. Един прост скрипт, преминаващ през всички стойности на enum на кръгове, трябва да помогне за генерирането на всички възможни тестове.
Сигурен съм, че можете също да използвате съществуваща рамка за модулен тест (като тази за повишаване) с тези шаблони, за да конструирате вашите тестове.
person
didierc
schedule
08.03.2013