Как уже указывалось в комментариях, вы должны остановить рекурсию, определив специализацию GenericMatrix. if(false)
оценивается во время выполнения (как уже указывалось в комментариях, функция c ++ 17 if consexpr
также может использоваться и здесь, однако следующий ответ не основан на этой функции, поскольку вопрос не помечен как c + +17). Это прямо отвечает на ваш первый вопрос. См. Следующий пример:
GenericMatrix<double,3,3> mat;
auto det = mat.GetDeterminant();
mat.GetDeterminant()
внутренне вызывает GetMinor
, который возвращает GenericMatrix<double,2,2>
. Теперь сам возвращаемый GenericMatrix<double,2,2>
-объект вызывает GetDeterminant
, и все начинается с начала, поскольку if(false)
не останавливает рекурсию времени компиляции. Следовательно, вы должны предоставить специализацию template<class T> GenericMatrix<T,1,1>
, чья GetDeterminant
не вызывает GetMinor
Что касается второго вопроса, вот упрощенный пример:
#include <iostream>
template<class T, unsigned int rows, unsigned int columns>
class GenericMatrix
{
public:
// Returns the determinant of the matrix
// Requires the matrix to be square
T GetDeterminant() const
{
T determinant = 0.;
std::cout << "call GenericMatrix<T," << rows <<","
<< columns <<">::GetDeterminant" << std::endl;
auto det_minor = this->GetMinor(0, 0).GetDeterminant();
// do semething with det_minor
return determinant;
}
private:
// Returns the minor of this matrix.
// Requires the matrix to be square.
// Will return a matrix[N - 1, N - 1] with a removed row and column.
GenericMatrix<T, rows - 1, columns - 1>
GetMinor(unsigned int rowToDelete, unsigned int columnToDelete) const
{
GenericMatrix<T, rows - 1, columns - 1> minor{};
std::cout << "call GenericMatrix<T,"
<< rows <<","<< columns <<">::GetMinor with return type "
<< "GenericMatrix<T," << rows-1 <<","
<< columns-1 <<">::GetDeterminant"
<< std::endl;
return minor;
}
T values[rows][columns] = { };
};
template<class T>
class GenericMatrix<T,1,1>
{
public:
// Returns the determinant of the matrix
T GetDeterminant() const
{
T determinant = 0.;
std::cout << "call GenericMatrix<T,1,1>::GetDeterminant" << std::endl;
return determinant;
}
private:
T value = { };
};
int main()
{
GenericMatrix<double,4,4> mat;
std::cout << mat.GetDeterminant() << std::endl;
return 0;
}
Вот скомпилированный код который выводит
call GenericMatrix<T,4,4>::GetDeterminant
call GenericMatrix<T,4,4>::GetMinor with return type GenericMatrix<T,3,3>::GetDeterminant
call GenericMatrix<T,3,3>::GetDeterminant
call GenericMatrix<T,3,3>::GetMinor with return type GenericMatrix<T,2,2>::GetDeterminant
call GenericMatrix<T,2,2>::GetDeterminant
call GenericMatrix<T,2,2>::GetMinor with return type GenericMatrix<T,1,1>::GetDeterminant
call GenericMatrix<T,1,1>::GetDeterminant
0