C++ 模板函数递归

问题描述 投票:0回答:1

我有一个计算矩阵行列式的函数。 我的矩阵类如下所示:

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)
。 为什么会出现该错误,如何修复它?

c++ templates recursion c++20
1个回答
1
投票

想象一下您用

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
}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.