问题描述
template<class T,class Derived>
class MatrixBase{
private:
//...
public:
Derived some_function(const Derived &other){
Derived& self = (Derived&)*this; // In my application I cant use static_cast.
// Some calculations...,which will determine the below
// defined variables "some_number_of_rows" and "some_number_of_cols"
// If Derived = DynamicMatrix<T>,then result should be declared as:
DynamicMatrix<T> result(some_number_of_rows,some_number_of_cols);
// while if Derived = StaticMatrix<T,Rows,Cols>,then result should be declared as:
StaticMatrix<T,some_number_of_rows,some_number_of_cols> result;
// Perform some more calculations...
return result;
}
};
template<class T>
class DynamicMatrix{
private:
size_t n_rows,n_cols;
T *data;
public:
DynamicMatrix(const size_t n_rows,const size_t n_cols);
// ...
};
template<class T,int Rows,int Cols>
class StaticMatrix{
private:
size_t n_rows = Rows,n_cols = Cols;
T data[Rows * Cols];
public:
StaticMatrix() {}
// ...
};
如何在MatrixBase::some_function(const Derived &other)
中检查派生类类型以在两个派生类中使用此基函数?,从而避免了分别在这些类中重新定义/覆盖/重复代码的需求。在这种情况下,基本上只有result
矩阵的声明才需要我检查Derived类的类型,因为该声明根据其固定大小或动态矩阵而有所不同。除类型检查外,也欢迎使用其他解决方案。
注意:由于我的应用程序的性质,我无法使用标准功能。
编辑:示例函数中的some_number_of_rows
和some_number_of_cols
通常不是constexpr,因为它们取决于对象矩阵的功能和大小。例如,对于transpose
函数,结果必须具有维度<Derived.n_cols,Derived.n_rows
,对于列式点积为<1,Derived.n_cols>
。
解决方法
这是一个具有挑战性的问题。基本上,some_number_of_rows
的{{1}}和some_number_of_cols
必须为constexpr
,而{em不能为{{1} } StaticMatrix
。
一种解决方案是将新的矩阵创建委托给派生类。它将以constexpr
或不以DynamicMatrix
的形式进行大小计算,以二者为准。
另一种方法是在CRTP类中进行两次大小计算,一次为constexpr
,另一次为constexpr
,并将两个结果都传递给派生的对象创建函数:constexpr
作为模板参数传递,非constexpr
作为常规参数传递。创建函数专门用于静态和动态矩阵。静态版本会忽略非constexpr
参数,反之亦然。
据我了解,您可以在Derived
中添加这些工厂方法:
如果在两种情况下,some_number_of_rows
,some_number_of_cols
都可以是constexpr(以满足更受约束的Derived
),则可以执行以下操作:
template<class T>
class DynamicMatrix
{
// ...
template <std::size_t Row,std::size_t Col>
static DynamicMatrix<T> Create() { return DynamicMatrix(Row,Col); }
};
template <class T,int Rows,int Cols>
class StaticMatrix{
// ...
template <std::size_t Row,std::size_t Col>
static StaticMatrix<T,Row,Col> Create() { return {}; }
};
使用
auto result = Derived::Create<some_number_of_rows,some_number_of_cols>();
否则,您也必须将计算移到派生函数中:
template<class T>
class DynamicMatrix
{
// ...
DynamicMatrix<T> CreateEmptyTransposed() const { return DynamicMatrix(n_cols,n_rows); }
};
template <class T,int Cols>
class StaticMatrix{
// ...
StaticMatrix<T,Cols,Row> CreateEmptyTransposed() const { return {}; }
};
使用
auto result = self.CreateEmptyTransposed();