避免在模板专业中避免代码重复
Avoiding code duplication in template specializations
本文关键字:代码 更新时间:2023-10-16
我有一个矩阵类
template<typename Type, size_t Rows, size_t Columns> class Matrix
{
public:
Type Entries[Rows][Columns];
// Operators, etc.
};
我需要对此类的专业(用于平方矩阵等(进行专业化,这意味着我需要为每个专业化重写整个类实现。然后,我开始考虑避免代码重复的方法。
想到的第一个想法是定义基本模板中的专业功能,但将它们删除,以便在基本模板中使用它们并在类外定义专业。
// Inside class definition
auto GetDeterminant() const -> T = delete;
// Outside class definition
template<typename Type, size_t Size> Matrix<T, Size, Size>::GetDeterminant() const -> T
{
// Implementation
}
但是,在遇到一些错误之后,我了解到不允许部分专门化功能模板。所以我尝试了这些方法
方法1:
template<typename Derived, typename Type, size_t Rows, size_t Columns> class MatrixBase
{
public:
T Entries[Row][Columns];
// Operators, etc.
}
template<typename Type, size_t Rows, size_t Columns> class Matrix : public MatrixBase<Matrix<Type, Rows, Columns>, Rows, Columns>
{
// General MxN matrix stuff
}
template<typename Type, size_t Size> class Matrix<T, Size, Size> : public MatrixBase<Matrix<T, Size, Size>, Size, Size>
{
public:
// Specific MxM matrix stuff
}
在这里,我在另一个问题上实现了 crtp ,但是我觉得抽象不需要,尽管可能有更好的方法。所以我想到了另一种方法。
方法2:
template<typename T, size_t Rows, size_t Columns> class Matrix
{
public:
T Entries[Rows][Columns]
auto GetDeterminant() const -> T
{
static_assert(Rows == Columns);
// Some computations
}
}
这似乎很好,如果有人试图在非平方矩阵上使用它,则会遇到编译时间错误。
问题:
有没有使用模板来解决此问题的方法?还是我应该坚持其中一种方法?
i使用sfinae提出了一种方法2的变体来启用或禁用GetDeterminant()
template <typename Type, size_t Rows, size_t Columns>
class Matrix
{
public:
Type Entries[Rows][Columns];
template <size_t R = Rows>
typename std::enable_if<R == Columns, Type>::type GetDeterminant () const
{
// some computations
return {};
}
};
如果要避免GetDeterminant()
可以验证模板R
值的风险,如下所示
Matrix<int, 3, 3> m0;
Matrix<long, 3, 2> m1;
auto d0 = m0.GetDeterminant(); // compile
//auto d1 = m1.GetDeterminant(); // compilation error
auto d1 = m1.GetDeterminant<2>(); // compile!!!
您可以维护static_assert
(例如static_assert(R == Rows, "!");
(,也可以如下改进std::enable_if
测试
template <size_t R = Rows>
typename std::enable_if<(R == Columns) && (R == Rows), Type>::type
GetDeterminant () const
{
// some computations
return {};
}
首先,引用Aschelper的评论:
我喜欢
static_assert
方法。
我也是。很明显,简洁,可以进一步给出有意义的解释错误消息。
助手struct
(在实现名称空间中(
namespace matrix_impl {
template<std::size_t Rows, std::size_t Columns>
struct determinate_calculation {
int operator()(int const (& entries)[Rows][Columns]) const = delete;
};
// or just don't define the class template
template<std::size_t Size>
struct determinate_calculation<Size, Size> {
int operator()(int const (& entries)[Size][Size]) const {
return entries[0][0]; // Woah, calculation wrong as hell ;)
}
};
}
template<std::size_t Rows, std::size_t Columns>
struct Matrix {
int entries[Rows][Columns];
int get_determinate() const {
return matrix_impl::determinate_calculation<Rows, Columns>{}(entries);
}
};
- (-1(需要类模板定义,包括删除函数或类模板声明。这只是样板。
- (-1(需要一个类模板专业化,其中包含某些函数中的实际代码。不仅仅是编写一个功能。
- (-1/1(需要将
Matrix
类的所需成员作为参数传递给该功能。很好,因为它使依赖关系明确。不好,因为有很多成员可能会变成麻烦("嘿,让我们使用一个类参数传递",只是添加到样板上(。
std::enable_if
max66更快,不再需要添加。
相关文章:
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 编译包含字符串的代码时遇到问题
- 我在c++代码中生成了一个运行时#3异常
- 如何在linux终端中同时编译和运行c++代码
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 在Linux for Windows上编译C++代码时出错
- 我的字符计数代码计算错误.为什么
- 孤立代码块在结构中引发异常
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 此代码是否违反一个定义规则
- 为什么我的代码在输出中增加了93天
- 我的简单if-else语句是如何无法访问的代码
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 为什么在这个代码结束循环中没有得到结束
- 在c代码之间共享数据的最佳方式
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值