Есть шаблонные классы
template< int rows, int columns, typename Type >
class Matrix : public Tensor
template< int size, typename Type >
class Vector : public Tensor
template< typename Type >
class Quaternion : public Tensor<4, Type> {...}
Которые все унаследованы от шаблонного базового класса:
template< int elements, typename Type = DEFUALT_TYPE >
class Tensor {
Tensor() {...}
Tensor( const Tensor
template< int elements, typename Type, typename Scalar >
friend Tensor< elements, Type> operator+( const Tensor< elements, Type>& left, const Scalar right );
...
// overloading operators -,*,/,+=,-=,*=,/=
protected:
Type array[elements];
}
Который, в основном, отвечает за базовые арифметические операции: сложение, вычитание, умножение, деление на скаляр, так как для всех наследованных типов эти операции одинаковы.
Но проблема в том, что эти операторы возвращают базовый класс Tensor, что, в свою очередь, порождает некоторые проблемы:
Нельзя присвоить результат сложение вектора и скаляра вектору:
Vector<3,double> vec1;
Vector<3,doubel> vec2 = vec1+1;
Для классов Matrix, Vector, Quaternion перегружен оператор стандартного вывода, но такое не сработает:
std::cout << vec1+2;
Нельзя сразу же использовать результат сложения:
(vec1+5).length();
Хотя, это почти то же самое что и 2 пункт.
Первую проблему можно решить, например, создав для Matrix, Vector, Quaternion конструктор копирования, который бы создавал объект из объекта класса Tensor:
Vector( const Tensor
Но это не решает остальных проблем, и пропускает такой, заведомо ложный код:
Matrix<2,2,double> mat1;
Vector<4,double> vec1 = mat1+2;
Сейчас я решил проблему тем, что для каждого наследуемого класса я определяю эти операторы заново. Но это во-первых муторно, ведь для каждого класса их примерно 12 штук. А если надо что-то поменять? Добавить новый класс? А во-вторых это дублирование идентичного кода.
Как можно разрешить эту проблему поэлегантнее?
Ответ
Можно воспользоваться техникой известной под именем CRTP.
Приведу пример, как Вам можно это реализовать, а Вы уже сами заточите под свой код:
#include
template
template
";
}
};
template
";
}
};
int main(int argc, char* argv[])
{
A
// Следующие строки не скомпилируются
//a = b + 1;
//b = a + 1;
}
Комментариев нет:
Отправить комментарий