Подход 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
с другой стороны, похоже, имеет свои размеры определяется во время выполнения. Но поскольку у вас есть отношение к измерениям, как указано выше, вы можете легко написать два тестовых примера в качестве шаблонов: один строит две матрицы с совпадающими размерами, а другой - с несовпадающими размерами.
Последний шаг — генерация всех возможностей. Простой сценарий, просматривающий все значения перечислений в раундах, должен помочь сгенерировать все возможные тесты.
Я уверен, что вы также можете использовать существующую среду модульного тестирования (например, boost) с этими шаблонами для создания своих тестов.
person
didierc
schedule
08.03.2013