多个类的父级的部分特化

Spa*_*rky 5 c++ templates policy-based-design

我想对模板类使用部分特化,以便该模板类的所有子节点都将使用该特化.让我用一个例子来解释:)

template < typename T, unsigned int rows, unsigned int cols>
class BaseMatrix {...};
Run Code Online (Sandbox Code Playgroud)

这个类将有子项指定矩阵的结构,如稀疏,密集,对角线,..

template < typename T, unsigned int rows, unsigned int cols>
class DiagonalMatrix : public BaseMatrix<T,rows,cols>{..}
Run Code Online (Sandbox Code Playgroud)

然后这些类将再次生成指定存储的子节点:堆栈数组,向量,列表,队列,..

template < typename T, unsigned int rows, unsigned int cols>
class StackDiagonalMatrix : public DiagonalMatrix<T, rows, cols> {..}
Run Code Online (Sandbox Code Playgroud)

然后有一个类Matrix,它提供所有数学功能.这个模板类实现了operator +,operator-等......

   template <typename T, 
             template<typename, unsigned, unsigned> class MatrixContainer,
             unsigned Rows, 
             unsigned Cols>
    class matrix;
Run Code Online (Sandbox Code Playgroud)

对于这最后一堂课,我想写下这样的专业:

template <typename T,unsigned Rows, unsigned Cols>
class matrix<T, BaseMatrix, Rows, Cols> {};

template <typename T,unsigned Rows, unsigned Cols>
class matrix<T, DiagonalMatrix, Rows, Cols>  {};
Run Code Online (Sandbox Code Playgroud)

但是当我编写一个继承自DiagonalMatrix的StackDiagonalMatrix时,它找不到DiagonalMatrix的特化 - 它实际上根本找不到专门化.

error: aggregate ‘matrix<int, StackDenseMatrix, 3u, 2u> matrix’ has incomplete type and cannot be defined
Run Code Online (Sandbox Code Playgroud)

现在有这个问题的解决方案吗?你能为几个模板类的父类编写专门化吗?

非常感谢!

涉及的完整来源:

    template <typename T, unsigned int rows, unsigned int cols>
    class BaseMatrix {
    protected:
        BaseMatrix(){};
        static const unsigned rowSize = rows;
        static const unsigned colSize = cols;
    };

    template <typename T, unsigned int rows, unsigned int cols>
    class DenseMatrix : public BaseMatrix<T, rows, cols> {
    protected:
        DenseMatrix(){};

    };

    template <typename T, unsigned int rows, unsigned int cols>
    class StackDenseMatrix : public DenseMatrix<T, rows, cols> {

    public:
        typedef T                                           value_type;

    private:
        value_type                                          grid[rows][cols];
        StackDenseMatrix();
    };

    template<typename value_type, unsigned int rows, unsigned int cols>
    StackDenseMatrix<value_type, rows,cols>::StackDenseMatrix () {
        for (unsigned int i = 0; i < this->rowSize; i++) {
            for (unsigned int j = 0; j < this->colSize; j++) {
                grid[i][j] = 0;
            }
        }
    }

    template <typename T, template<typename, unsigned, unsigned> class MatrixContainer ,unsigned Rows, unsigned Cols>
    class matrix;

    template <typename T,unsigned Rows, unsigned Cols>
    class matrix<T,BaseMatrix, Rows, Cols> {
         matrix(){};
};

int main () {
    matrix<int, StackDenseMatrix, 3, 2> matrix;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*son 4

继承不适用于模板特化。当您调用时matrix<int,StackDenseMatrix,3,2> matrix;,它将选择 的通用模板matrix,因为第二个参数是StackDenseMatrix, not BaseMatrix。即使这些类通过继承相关,但没有任何区别,它们不是完全相同的类型,因此编译器不会选择matrix.

为了解决你的问题,我认为继承在这种情况下不会给你带来任何好处。在泛型编程中,更合适的工具是类型特征、策略和概念。在这种情况下,您应该能够应用一些类型特征来实现类似的目标。我喜欢使用的一个技巧是默认模板参数依赖于先前的模板参数,然后进行部分特化。例如如下:

enum MatrixStorage {
  DenseMatrix,
  SparseMatrix
};

enum MatrixStructure {
  GeneralMatrix,
  SquareMatrix,
  DiagonalMatrix  //, ...
};

template <typename T, unsigned Rows, unsigned Cols>
class StackDenseMatrix {
  public: 
    typedef T value_type;
    static const MatrixStorage Storage = DenseMatrix;
    static const MatrixStructure Structure = GeneralMatrix;
  //..
};

//General template with default arguments:
template <typename T, 
          template <typename, unsigned, unsigned> class MatrixContainer,
          unsigned Rows, unsigned Cols, 
          MatrixStorage Storage = MatrixContainer<T,Rows,Cols>::Storage,
          MatrixStructure Structure = MatrixContainer<T,Rows,Cols>::Structure>
class matrix;

//Specialization with given arguments:
template <typename T, 
          template <typename, unsigned, unsigned> class MatrixContainer,
          unsigned Rows, unsigned Cols>
class matrix<T,MatrixContainer,Rows,Cols,DenseMatrix,GeneralMatrix> {
  //implementation of matrix for when the container is dense and has general structure...
};

int main() {
  matrix<int,StackDenseMatrix,3,2> M; //no extra arguments, and the right specialization will be selected based on the traits of StackDenseMatrix.
  return 0;
};
Run Code Online (Sandbox Code Playgroud)

我有自己的矩阵库,它严重依赖于模板元编程和通用编程技术,类似于上面的示例,为不同类型的矩阵结构和存储提供矩阵运算的特殊实现,并且这种方式工作得很好。我曾经对不同的矩阵类型使用继承,但现在我转而仅依赖类型特征、概念、策略和 Sfinae 开关,这是一个更实用的解决方案。