多个类的父类的部分特化
我想对模板类使用部分专业化,以便该模板类的所有子级都将使用该专业化。让我用一个例子来解释它:)
template < typename T, unsigned int rows, unsigned int cols>
class BaseMatrix {...};
这个类将有指定矩阵结构的子类,如稀疏、密集、对角线等。
template < typename T, unsigned int rows, unsigned int cols>
class DiagonalMatrix : public BaseMatrix<T,rows,cols>{..}
然后这些类将再次有指定存储的子类:堆栈数组、向量、列表、队列,..
template < typename T, unsigned int rows, unsigned int cols>
class StackDiagonalMatrix : public DiagonalMatrix<T, rows, cols> {..}
然后是一个 Matrix 类,它提供了所有的数学功能。这个模板类实现了operator+、operator-等...
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> {};
template <typename T,unsigned Rows, unsigned Cols>
class matrix<T, DiagonalMatrix, Rows, Cols> {};
但是当我编写一个继承自DiagonalMatrix的StackDiagonalMatrix时,它没有找到DiagonalMatrix的专业化——它没有找到实际上根本就是一个专业。
error: aggregate ‘matrix<int, StackDenseMatrix, 3u, 2u> matrix’ has incomplete type and cannot be defined
现在这个问题有解决办法吗?您可以为多个模板类的父类编写专门化吗?
非常感谢!
涉及的完整来源:
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;
}
I want to use partial specialization for a template class so that all children of that template class will use that specialization. Let me explain it with an example :)
template < typename T, unsigned int rows, unsigned int cols>
class BaseMatrix {...};
This class will have children that specify the structure of the matrix, like sparse,dense,diagonal,..
template < typename T, unsigned int rows, unsigned int cols>
class DiagonalMatrix : public BaseMatrix<T,rows,cols>{..}
Then those classes will have children again that specify the storage : stack arrays, vectors, list, queues,..
template < typename T, unsigned int rows, unsigned int cols>
class StackDiagonalMatrix : public DiagonalMatrix<T, rows, cols> {..}
Then there is a class Matrix, which provides all the mathematical functionality. This template class implements operator+, operator-, etc...
template <typename T,
template<typename, unsigned, unsigned> class MatrixContainer,
unsigned Rows,
unsigned Cols>
class matrix;
For this last class I want to write specializations like this:
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> {};
But when I write a StackDiagonalMatrix which inherits from DiagonalMatrix, it does not find the specialization for DiagonalMatrix -- it does not find a specialization at all actually.
error: aggregate ‘matrix<int, StackDenseMatrix, 3u, 2u> matrix’ has incomplete type and cannot be defined
Now is there a solution for this problem? Can you write a specialization for a parent of several template classes?
Many thanks!
Full Source that is involved :
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
继承不适用于模板特化。当您调用matrix时,它会选择
matrix
的通用模板,因为第二个参数是StackDenseMatrix
,而不是BaseMatrix
。即使这些类通过继承相关,但没有任何区别,它们不是完全相同的类型,因此编译器不会选择matrix
的特化。为了解决你的问题,我认为继承在这种情况下不会给你带来任何好处。在泛型编程中,更合适的工具是类型特征、策略和概念。在这种情况下,您应该能够应用一些类型特征来实现类似的目标。我喜欢使用的一个技巧是默认模板参数依赖于先前的模板参数,然后进行部分特化。例如如下:
我有自己的矩阵库,它严重依赖于模板元编程和通用编程技术,按照上面的示例,为不同类型的矩阵结构和存储提供矩阵运算的特殊实现,并且它非常有效好这样。我曾经对不同的矩阵类型使用继承,但现在我转而仅依赖类型特征、概念、策略和 Sfinae 开关,这是一个更实用的解决方案。
Inheritance does not apply to template specializations. When you invoke
matrix<int,StackDenseMatrix,3,2> matrix;
, it will select the general template formatrix
, because the second argument isStackDenseMatrix
, notBaseMatrix
. Even though those classes are related through inheritance, it doesn't make any difference, they are not of the exact same type, so the compiler won't select the specialization ofmatrix
.To solve your problem, I don't think inheritance will do you any good in this case. In generic programming, the more appropriate tools are type-traits, policies and concepts. In this case, you should be able to apply some type-traits to achieve similar goals. One trick I like to use is the default template argument that depends on a previous template argument, and then do a partial specialization. As follows for example:
I have my own matrix library that heavily relies on template meta-programming and generic programming techniques along the lines of the above example to provide special implementation of matrix operations for different type of matrix structures and storage, and it works very well this way. I used to use inheritance for the different matrix types, but I have now switched to relying only on type-traits, concepts, policies and Sfinae switches, that is a much more practical solution.
为了解决您的问题,您可以使用基于策略的设计。例如,您可以创建存储和形状的策略类。
此处使用基于策略的设计的主要优点是您的用户可以轻松提供自己的存储设施和形状操作。您需要做的就是给他们一个清晰的界面,以便他们知道如何制作自己的存储设施和形状操作。
To solve your problem, you can use policy-based design. You can make for instance policy classes of Storage and Shape.
The major advantage of using policy-based design here is that your users can easily provide their own storage facilities and shape operations. All you need to do is give them a clear interface so that they know how they can make their own storage facilities and shape operations.