c++ - 不同的模板类实现但相同的成员函数
问题描述
我有一个模板矩阵类,其中包含一些典型的成员函数,例如inverse
、determinant
、operator*
等。我想在模板实现中重用这些成员函数的代码,用于固定和动态大小的矩阵。
这可能吗?如果是,如何?
在下面的代码中,像 Eigen 一样,我使用 " -1
" 表示动态尺寸。是的,我知道我可以为此使用库,但对于我的应用程序,这是不可行的。由于应用程序的性质(CUDA),标准功能是不可能的
是否可以根据模板参数制作具有不同成员变量大小的模板类?例如 whenDynamic_Rows = -1
和Dynamic_Cols = -1
,则数据为T **data
,否则为T data[Rows][Cols]
。
到目前为止,我有一个用于动态大小矩阵的模板类(下面的“最小”示例,请注意代码可能会出现错误/错误,因为我对“高级”类模板比较陌生)。
但是在固定大小的矩阵实例化的情况下,我希望有一个固定大小的数据成员变量。
template<class T, int Dynamic_Rows, int Dynamic_Cols>
class CMatrix<T, -1, -1>
{
private:
size_t n_rows, n_cols;
T** data;
void allocate_data();
void deallocate_data();
public:
CMatrix(const size_t n_rows, const size_t n_cols);
CMatrix(const CMatrix& other);
~CMatrix();
CMatrix& operator=(const CMatrix& rhs);
CMatrix exp() const;
};
例如exp()
下面函数的代码为
template <class T, int Dynamic_Rows, int Dynamic_Cols>
CMatrix<T, -1, -1> CMatrix<T, -1, -1>::exp() const
{
CMatrix<T, -1, -1> result(n_rows, n_cols);
for (size_t i = 0; i < n_rows; i++)
{
for (size_t j = 0; j < n_cols; j++)
{
result.data[i][j] = exp(result.data[i][j]);
}
}
return result;
}
我现在唯一能想到的同时允许动态和固定大小的矩阵是基本上实现该类的另一个模板作为
template<class T, size_t Rows, size_t Cols>
class CMatrix<T, Rows, Cols>
{
private:
size_t n_rows = Rows, n_cols = Cols;
T data[Rows][Cols];
public:
CMatrix() {}
CMatrix(const CMatrix& other);
CMatrix& operator=(const CMatrix& rhs);
CMatrix exp() const;
};
使用可变参数模板
template<class T, int...> class CMatrix;
但这只会复制我的大多数成员函数的代码!
解决方案
这是使用 CRTP 进行此类专业化的一种非常通用的方法。它不要求有一个简单的单一条件可用于选择数据成员的实现,而其余部分保持不变。
template <class T, class Impl> class MatrixBase {
// data is NOT defined here
Impl exp() const
{
Impl& self = static_cast<Impl&>(*this); // <-- this is magic
Impl result = self; // <-- this is magic
for (size_t i = 0; i < n_rows; i++)
{
for (size_t j = 0; j < n_cols; j++)
{
result.data[i][j] = exp(result.data[i][j]); // <-- data is defined in Impl
}
}
return result;
}
// other functions that do not depend on actual type of data
};
template <class T>
class DynamicMatrix : public MatrixBase<T, DynamicMatrix<T>> {
T** data;
// define constructors etc here
};
template <class T, int Rows, int Cols>
class StaticMatrix : public MatrixBase<T, StaticMatrix<T, Rows, Cols>> {
T[Rows][Cols] data;
// define constructors etc here
};
现在您已经拥有了StaticMatrix
and DynamicMatrix
,如果您愿意,可以将它们统一为一个别名模板。
template <class T, int Rows, int Cols>
using CMatrix = std::conditional_t <(Rows >= 0 && Cols >= 0),
StaticMatrix<T, Rows, Cols>,
DynamicMatrix<T>
>;
推荐阅读
- git - 如何将文件从一个 git 分支移动到另一个
- gitlab - 尝试在 gitlab ci 中列出里程碑时未授权
- r - 寻找直方图的 AUC
- typescript - 在 Amplify/Appsync 中定义预计算列的正确方法
- java - 使用 CompletableFuture 时如何保留 JPA Fetch 子数据?
- mongodb - 插座中的猫鼬手表
- azure - 天蓝色模板不允许作业关键字
- c# - 单击按钮时如何使其他控件看起来更暗?
- linux - 在 vncviewer 中依次闪烁,就像有一些超级刮刀在工作一样
- outlook - 我们可以在 Outlook 插件的邮箱项目中添加自定义隐藏字段吗?