我有一个计算矩阵行列式的函数。 我的矩阵类如下所示:
template <int Col, int Row, typename T>
class Matrix;
我为
Mat<1, 1, T>
、Mat<2, 2, T>
和Mat<3, 3, T>
实现了三个特定功能:
template <typename T>
float Determinant(const Matrix<1, 1, T>& mat);
template <typename T>
float Determinant(const Matrix<2, 2, T>& mat);
template <typename T>
float Determinant(const Matrix<3, 3, T>& mat);
现在我想要一个函数来计算矩阵的行列式 尺寸大于 3x3。我尝试像这样实现它:
template <int Dim, typename T>
float Determinant(const Matrix<Dim, Dim, T>& mat)
{
float result = 0;
for (int i = 0; i < Dim; ++i)
{
// This function returns a minor matrix of `mat`
Matrix<Dim - 1, Dim - 1, T> minor = mat.GetMinorMatrix(i, 0);
result += (i & 1 ? -1 : 1) * mat(i, 0) * Determinant(minor);
}
}
// I try to use the function
Matrix<1, 1, float> mat { 1.0f };
Determinant(mat); // Error occurs here
但不知何故,当我尝试构建该代码时,我的编译器不断崩溃。我的 IDE 报告了这个错误:
In template: recursive template instantiation exceeded maximum depth of 1024
。当我删除该函数时,错误消失了template <int Dim, typename T> float Determinant(const Matrix<Dim, Dim, T>& mat)
。
为什么会出现该错误,如何修复它?
想象一下您用
Determinant
实例化 Dim = 0
。您的编译器将尝试实例化 Determinant<-1>
,然后再次实例化 Determinant<-2>
,依此类推。在某些时候,您将达到最大值 1024。最小的可重现示例可能如下所示:
template <int I>
void foo() {
foo<I - 1>();
}
int main() {
foo<5>();
}
您可以通过不同的方式解决这个问题。更现代的方法将检查最终的递归调用:
template <int I>
void foo() {
if constexpr (I > 0) {
foo<I - 1>();
} else {
// however you want to deal with I = 0
}
}
或者使用模板模式匹配:
template <int I>
void foo() {
foo<I - 1>();
}
template <>
void foo<0>() {
// however you want to deal with I = 0
}