2016-03-10 2 views
1

я написал общий класс матрицы следующим образом:Как частично специализировать шаблонный класс C++?

template <std::size_t N, std::size_t M, class T> 
class CMatrix 
{ 
protected: 
    T* m_elem; 
public: 
    CMatrix() : m_elem(new T[N*M]) {} 
    ~CMatrix() { delete[] m_elem; } 
    inline bCMatrix& operator*=(const T& val); 
    inline bCMatrix& operator/=(const T& val); 
    ... 
    template <std::size_t L> inline CMatrix<L, N, T> operator*(const CMatrix<M, L, T>& mat) const; 
}; 

Теперь я хотел бы сделать несколько специализаций для CMatrix < 2,2, T>. Я хотел бы добавить компромисс CMatrix<2,2,T>(const T& a00, const T& a01, const T& a10, const T& a11) {...}. И мне нравится специализировать матричное умножение для CMatrix < 2x2> * CMatrix < 2x2>. Но, с другой стороны, я хотел бы сохранить функции * = и/= и т. Д.

Как мне это сделать?

Моя единственная рабочая попытка переписать (копировать/прошлое/поиск/замена) весь код для специализации N = 3, M = 3, как:

template <class T> 
class CMatrix<3,3,T> 
{ 
... 
}; 

Теперь я могу специализировать матричным матричное умножение для 2x2. Но у меня есть два почти одинаковых фрагмента кода, например, один для умножения матричных векторов и один для умножения матрицы-вектора с матрицей 2x2. Который должен быть изменен, если я оптимизирую общий. Отстойно это поддерживать.

+2

Каковы ваши попытки? – sgvd

+4

'template class CMatrix <2, 2, T> {};' – Cornstalks

+0

Сначала я хотел бы спросить, почему вы используете указатель с динамическим распределением вместо массива? Поскольку 'N' и' M' известны во время компиляции, вы можете просто использовать 'T m_elem [N * M];' – NathanOliver

ответ

3

Вы можете прочитать документацию по шаблону класса, например http://en.cppreference.com/w/cpp/language/partial_specialization. Для вас это влечет за собой определение специализации таким образом, как это:

template<typename T> 
class CMatrix<2, 2, T> 
{ 
public: 
    CMatrix<2,2,T>(const T& a00, const T& a01, const T& a10, const T& a11); 
    ... 
    template <std::size_t L> inline CMatrix<L, 2, T> operator*(const CMatrix<2, L, T>& mat) const; 

    // Special overload for 2x2 x 2x2 multiplication 
    inline CMatrix<2, 2, T> operator*(const CMatrix<2, 2, T>& mat) const; 
}; 

Чтобы избежать дублирования кода для operator*= и т.д. Вы можете сделать template<int M, int N, typename T> class CMatrixBase {} и осуществлять их там, и есть фактические классы матриц и специализаций наследуют от ,

Мартин предложил использовать CRTP, который поможет вам не потерять информацию о типе. Это будет выглядеть так:

template<int M, int N, typename T, typename Derived> 
class CMatrixBase 
{ 
public: 
    Derived& operator*=(T val) { 
     doMultiplication(val); 
     return *static_cast<Derived*>(this); 
    } 
}; 
+0

CRTP выглядит многообещающим.Таким образом, он сводится к шаблону class CMatrix: public CMatrixBase > {}; Но у CMatrixBase только есть доступ к CMatrix , нет возможности использовать шаблон CMatrix . Или я ошибаюсь? – PanicSheep