首页 > 解决方案 > CRTP:确定基类函数中的派生类类型以允许代码重用

问题描述

假设我有一个矩阵的 CRTP 模板类

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矩阵的声明需要我检查派生类类型,因为声明是不同的,具体取决于它是固定大小的矩阵还是动态矩阵。也欢迎除类型检查之外的其他解决方案。

注意:由于我的应用程序的性质,我不能使用标准功能。

编辑:示例函数中的some_number_of_rowsandsome_number_of_cols通常不是 constexpr,因为它们取决于对象矩阵的函数和大小。例如,对于一个transpose函数,结果必须具有维度<Derived.n_cols, Derived.n_rows,并且在按列点积的情况下,<1, Derived.n_cols>

标签: c++templatescrtp

解决方案


这是一个具有挑战性的问题。基本上,some_number_of_rows并且some_number_of_cols 必须constexpr的情况下StaticMatrix,并且不能constexpr的情况下DynamicMatrix

一种解决方案是将新矩阵的创建委托给派生类。它将按constexpr或不进行大小计算constexpr,以适合它的为准。

另一种是在 CRTP 类中进行大小计算两次,一次 asconstexpr和一次 not constexpr,并将两个结果都传递给派生对象创建函数:constexpr作为模板参数传递,而非constexpr作为常规参数传递。创建函数专门用于静态和动态矩阵。静态版本忽略非constexpr参数,反之亦然。


推荐阅读