Adv*_* GS 2 c++ recursion templates matrix determinants
我正在使用 C++ 和 g++(版本 13.2.1),并且我正在创建一个Determinant<m>接受std::array<std::array<int,m>,m>参数类型并返回该矩阵的行列式的函数。
以下是我写的代码。
\n行列式:
\ntemplate <int m>\nint Determinant(std::array<std::array<int,m>,m> arr){\n\n if(m == 2){\n return arr[0][0]*arr[1][1] - arr[0][1]*arr[1][0];\n }else if(m >2){\n int ans = 0;\n for(int i =0;i < m;i++){\n ans += arr[0][i]*Determinant<m-1>(slc<m,m>( arr,i,0 ))*(i%2 ? 1:-1);\n }\n return ans;\n }else{\n return -1;\n\n }\n }\nRun Code Online (Sandbox Code Playgroud)\nslc :返回一个切片(不是真正的切片,只是删除一行和一列)
\ntemplate <int m, int n>\nstd::array<std::array<int,(n-1)>,(m-1)> slc(std::array<std::array<int,n>,m> arr, int i,int j){\n std::array<std::array<int,(n-1)>,(m-1)> ans;\n\n for(int x = 0;x < m;x ++){\n for (int y = 0;y < n;y++){\n if(y == i || x == j){\n continue;\n }\n ans[x- ( x>j ? 1:0) ][y- ( y>i ? 1:0) ] = arr[x][y];\n }\n }\n return ans;\n\n}\nRun Code Online (Sandbox Code Playgroud)\n我收到的错误附在这里:
\nmatrices.cpp: In instantiation of \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 0]\xe2\x80\x99:\nmatrices.cpp:85:42: recursively required from \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 2]\xe2\x80\x99\nmatrices.cpp:85:42: required from \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 3]\xe2\x80\x99\nmatrices.cpp:98:30: required from here\nmatrices.cpp:85:51: warning: size of \xe2\x80\x98<anonymous>\xe2\x80\x99 18446744039349813252 bytes exceeds maximum object size 9223372036854775807 [-Wlarger-than=]\n 85 | ans += arr[0][i]*Determinant<m-1>(slc<m,m>( arr,i,0 ))*(i%2 ? 1:-1);\n | ~~~~~~~~^~~~~~~~~~~\nmatrices.cpp:85:51: warning: size of \xe2\x80\x98<anonymous>\xe2\x80\x99 18446744039349813252 bytes exceeds maximum object size 9223372036854775807 [-Wlarger-than=]\nIn file included from matrices.cpp:2:\n/usr/include/c++/13/array: In instantiation of \xe2\x80\x98struct std::__array_traits<std::array<int, 18446744073709551615>, 18446744073709551615>\xe2\x80\x99:\nmatrices.cpp:85:42: recursively required from \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 2]\xe2\x80\x99\nmatrices.cpp:85:42: required from \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 3]\xe2\x80\x99\nmatrices.cpp:98:30: required from here\n/usr/include/c++/13/array:55:13: error: size \xe2\x80\x9818446744073709551615\xe2\x80\x99 of array exceeds maximum object size \xe2\x80\x989223372036854775807\xe2\x80\x99\n 55 | using _Type = _Tp[_Nm];\n | ^~~~~\n/usr/include/c++/13/array: In instantiation of \xe2\x80\x98struct std::__array_traits<int, 18446744073709551615>\xe2\x80\x99:\n/usr/include/c++/13/array:109:55: recursively required from \xe2\x80\x98struct std::array<int, 18446744073709551615>\xe2\x80\x99\nmatrices.cpp:85:42: recursively required from \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 2]\xe2\x80\x99\nmatrices.cpp:85:42: required from \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 3]\xe2\x80\x99\nmatrices.cpp:98:30: required from here\n/usr/include/c++/13/array:55:13: error: size \xe2\x80\x9818446744073709551615\xe2\x80\x99 of array exceeds maximum object size \xe2\x80\x989223372036854775807\xe2\x80\x99\nmatrices.cpp: In instantiation of \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 0]\xe2\x80\x99:\nmatrices.cpp:85:42: recursively required from \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 2]\xe2\x80\x99\nmatrices.cpp:85:42: required from \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 3]\xe2\x80\x99\nmatrices.cpp:98:30: required from here\nmatrices.cpp:85:51: error: could not convert \xe2\x80\x98slc<0, 0>(arr, i, 0)\xe2\x80\x99 from \xe2\x80\x98array<array<[...],4294967295>,4294967295>\xe2\x80\x99 to \xe2\x80\x98array<array<[...],18446744073709551615>,18446744073709551615>\xe2\x80\x99\n 85 | ans += arr[0][i]*Determinant<m-1>(slc<m,m>( arr,i,0 ))*(i%2 ? 1:-1);\n | ~~~~~~~~^~~~~~~~~~~\n | |\n | array<array<[...],4294967295>,4294967295>\nmatrices.cpp: In instantiation of \xe2\x80\x98std::array<std::array<int, (n - 1)>, (m - 1)> slc(std::array<std::array<int, n>, m>, int, int) [with unsigned int m = 0; unsigned int n = 0]\xe2\x80\x99:\nmatrices.cpp:85:42: recursively required from \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 2]\xe2\x80\x99\nmatrices.cpp:85:42: required from \xe2\x80\x98int Determinant(std::array<std::array<int, m>, m>) [with int m = 3]\xe2\x80\x99\nmatrices.cpp:98:30: required from here\nmatrices.cpp:6:43: warning: size of \xe2\x80\x98ans\xe2\x80\x99 18446744039349813252 bytes exceeds maximum object size 9223372036854775807 [-Wlarger-than=]\n 6 | std::array<std::array<int,(n-1)>,(m-1)> ans;\n | ^~~\nmatrices.cpp:15:10: warning: size of \xe2\x80\x98<anonymous>\xe2\x80\x99 18446744039349813252 bytes exceeds maximum object size 9223372036854775807 [-Wlarger-than=]\n 15 | return ans;\n | ^~~\nmatrices.cpp:15:10: warning: size of \xe2\x80\x98<anonymous>\xe2\x80\x99 18446744039349813252 bytes exceeds maximum object size 9223372036854775807 [-Wlarger-than=]\nRun Code Online (Sandbox Code Playgroud)\n任何见解将不胜感激。
\n首先,如果存在类型不匹配,则不可能进行推导。与中的int m类型不同,因此您应该使用:mstd::array<int, m>
template <std::size_t m>
Run Code Online (Sandbox Code Playgroud)
其次,模板实例化中存在无限递归,因为您没有使用if constexpr,而只是使用常规if语句。在 中if (m == 2){,如果条件为假,代码块不会被丢弃,它只是变成死代码。这同样适用于else分支机构。
因此,Determinant<2>实例化Determinant<1>、then Determinant<0>、然后Determinant<-1>是编译器错误的地方。要解决此问题,请使用if constexpr:
template <std::size_t m>
int Determinant(std::array<std::array<int, m>, m> arr) {
if constexpr (m == 0) {
return -1;
} else if constexpr (m == 1) {
return arr[0][0];
} else if constexpr (m == 2) {
return arr[0][0] * arr[1][1] - arr[0][1] * arr[1][0];
} else {
int ans = 0;
for (std::size_t i = 0; i < m; i++) {
ans += arr[0][i] * Determinant<m-1>(slc<m, m>(arr, i, 0)) * (i % 2 ? 1 : -1);
}
return ans;
}
}
Run Code Online (Sandbox Code Playgroud)
另请参阅:“if constexpr()”与“if()”之间的区别