使用std::array与模板实现行列式计算时遇参数不匹配错误
问题:模板参数推导失败导致无法调用矩阵相关函数
我尝试编写一个计算N阶矩阵行列式的程序,借此首次学习std::array和模板,基于余子式与子式方法完成了如下实现:
#include <array> #include <iostream> template <int N> using Matrix = std::array<std::array<double, N>, N>; template <int N> Matrix<N - 1> subMatrix(Matrix<N> matrix, size_t focusRow, size_t focusColumn) { Matrix<N - 1> returnMatrix; int subMatrixRow = 0, subMatrixColumn = 0; static const int matrixSize = matrix.size(); for (size_t matrixRow = 0; matrixRow < matrixSize; matrixRow++) { for (size_t matrixColumn = 0; matrixColumn < matrixSize; matrixColumn++) { if (matrixRow != focusRow && matrixColumn != focusColumn) { returnMatrix[subMatrixRow][subMatrixColumn++] = matrix[matrixRow][matrixColumn]; if (subMatrixColumn == matrixSize - 1) { subMatrixColumn = 0; subMatrixRow++; } } } } return returnMatrix; } template <int N> double getDeterminant(Matrix<N> matrix) { static const int matrixSize = matrix.size(); double determinant = 0; if (matrixSize == 1) { determinant = matrix[0][0]; } else if (matrixSize == 2) { determinant = (matrix[0][0] * matrix[1][1]) - (matrix[0][1] * matrix[1][0]); } else if (matrixSize > 0) { int sign = 1; for (size_t dimension = 0; dimension < N; dimension++) { determinant += sign * matrix[0][dimension] * getDeterminant(subMatrix(matrix, 0, dimension)); sign = -sign; } } else { throw std::invalid_argument("expected square matrix"); } return determinant; } int main(int argc, char const* argv[]) { static const int length = 3; Matrix<length> matrix = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; printf("determinant = %.2f\n", getDeterminant(matrix)); }
执行make编译时出现如下错误:
vscode ➜ /workspaces/c-cpp-mirror/11032023-arrays $ make determinant g++ determinant.cpp -o determinant determinant.cpp: In function ‘int main(int, const char**)’: determinant.cpp:68:57: error: no matching function for call to ‘getDeterminant(Matrix<3>&)’ 68 | printf("determinant = %.2f\n", getDeterminant(matrix)); | ^ determinant.cpp:31:8: note: candidate: ‘template<int N> double getDeterminant(Matrix<N>)’ 31 | double getDeterminant(Matrix<N> matrix) { | ^~~~~~~~~~~~~~ determinant.cpp:31:8: note: template argument deduction/substitution failed: determinant.cpp:68:57: note: mismatched types ‘int’ and ‘long unsigned int’ 68 | printf("determinant = %.2f\n", getDeterminant(matrix)); | ^ make: *** [<builtin>: determinant] Error 1
以下是能复现该问题的简化程序:
#include <array> #include <iostream> template <int N> using Matrix = std::array<std::array<double, N>, N>; template <int N> void printMatrix(Matrix<N> matrix) {} int main(int argc, char const* argv[]) { static const int length = 4; Matrix<length> matrix = {{{7, -2, 2, 1}, {3, 1, -5, 2}, {2, 2, -5, 3}, {3, 2, 5, 1}}}; printMatrix(matrix); }
解决方法
问题根源
模板参数推导时,std::array::size()返回的是无符号整数类型(size_t),但代码中模板参数N被定义为signed int类型,类型不匹配导致推导失败。
方案1:显式指定模板参数
调用函数时手动指定模板参数,跳过自动推导:
// 原main函数中的调用修改为 printf("determinant = %.2f\n", getDeterminant<length>(matrix)); // 简化程序中的调用修改为 printMatrix<length>(matrix);
方案2:统一模板参数类型为无符号整数
将模板参数的int N改为std::size_t N(需包含<cstddef>头文件),与std::array的尺寸类型保持一致:
#include <array> #include <iostream> #include <cstddef> // 新增头文件 template <std::size_t N> using Matrix = std::array<std::array<double, N>, N>; template <std::size_t N> Matrix<N - 1> subMatrix(Matrix<N> matrix, size_t focusRow, size_t focusColumn) { Matrix<N - 1> returnMatrix; int subMatrixRow = 0, subMatrixColumn = 0; constexpr std::size_t matrixSize = N; // 直接用模板参数,无需调用size() for (size_t matrixRow = 0; matrixRow < matrixSize; matrixRow++) { for (size_t matrixColumn = 0; matrixColumn < matrixSize; matrixColumn++) { if (matrixRow != focusRow && matrixColumn != focusColumn) { returnMatrix[subMatrixRow][subMatrixColumn++] = matrix[matrixRow][matrixColumn]; if (subMatrixColumn == matrixSize - 1) { subMatrixColumn = 0; subMatrixRow++; } } } } return returnMatrix; } template <std::size_t N> double getDeterminant(Matrix<N> matrix) { constexpr std::size_t matrixSize = N; double determinant = 0; if (matrixSize == 1) { determinant = matrix[0][0]; } else if (matrixSize == 2) { determinant = (matrix[0][0] * matrix[1][1]) - (matrix[0][1] * matrix[1][0]); } else if (matrixSize > 0) { int sign = 1; for (size_t dimension = 0; dimension < N; dimension++) { determinant += sign * matrix[0][dimension] * getDeterminant(subMatrix(matrix, 0, dimension)); sign = -sign; } } else { throw std::invalid_argument("expected square matrix"); } return determinant; } int main(int argc, char const* argv[]) { static const std::size_t length = 3; // 同步修改类型 Matrix<length> matrix = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; printf("determinant = %.2f\n", getDeterminant(matrix)); }
同时,代码中static const int matrixSize = matrix.size();可以替换为constexpr std::size_t matrixSize = N;,因为N是编译期已知的模板参数,无需运行时调用size()方法,效率更高。
内容的提问来源于stack exchange,提问作者eccentricOrange
相关产品推荐
相关产品推荐

