Closed nicovank closed 1 year ago
The example is a bit silly, but this is the first thing I could think of for a infinite recursive template.
LGTM. Nit: GPT produced an English syntax error?!?
This will allocates memory needed for the vector v.
Didn't event notice, seems so, I copy-pasted from the output 🤷
Impressive snippet: I originally forgot to pass the vector size
M * N
when constructing the vector (std::vector<std::uint64_t> v;
, which doesn't generate a compiler diagnostic at all, would SIGSEV), and GPT reported it.This will allocates memory needed for the vector v. Without this, your current program is accessing out-of-bounds memory in line
v[i] = i;
, which also causes a runtime error.fatal error: recursive template instantiation exceeded maximum depth of 1024 tests/c++/template-recursion.cpp:11:51: note: while substituting deduced template arguments into function template 'span' [with _Range = std::span &]
Matrix(std::span underlying) : underlying(underlying) {
^
tests/c++/template-recursion.cpp:19:32: note: in instantiation of member function 'Matrix<4294966373, 10>::Matrix' requested here
const auto subMatrix = Matrix<M - 1, N>(underlying.subspan(N));
^
tests/c++/template-recursion.cpp:20:48: note: in instantiation of member function 'Matrix<4294966374, 10>::lowestRowSum' requested here
return std::min(firstRowSum, subMatrix.lowestRowSum());
^
tests/c++/template-recursion.cpp:20:48: note: in instantiation of member function 'Matrix<4294966375, 10>::lowestRowSum' requested here
tests/c++/template-recursion.cpp:20:48: note: in instantiation of member function 'Matrix<4294966376, 10>::lowestRowSum' requested here
tests/c++/template-recursion.cpp:20:48: note: (skipping 1015 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
tests/c++/template-recursion.cpp:20:48: note: in instantiation of member function 'Matrix<96, 10>::lowestRowSum' requested here
tests/c++/template-recursion.cpp:20:48: note: in instantiation of member function 'Matrix<97, 10>::lowestRowSum' requested here
tests/c++/template-recursion.cpp:20:48: note: in instantiation of member function 'Matrix<98, 10>::lowestRowSum' requested here
tests/c++/template-recursion.cpp:20:48: note: in instantiation of member function 'Matrix<99, 10>::lowestRowSum' requested here
tests/c++/template-recursion.cpp:36:47: note: in instantiation of member function 'Matrix<100, 10>::lowestRowSum' requested here
const auto lowestRowSum = Matrix<M, N>(v).lowestRowSum();
^
1 error generated.
Your issue originates from the fact that when the
Matrix<M, N>
template is instantiated, it recursively creates a newMatrix<M - 1, N>
object in thelowestRowSum
method (at line 19). This recursion has no base case, meaning that it continues infinitely (until the compiler puts a stop to it after 1024 iterations).For a recursive template, you have to provide a base case to terminate the recursion. Something like this:
In the code above, the
if
statement with theconstexpr
keyword creates a compile-timeif
statement, meaning that if the condition isfalse
, the branch is not even compiled. Effectively, thelowestRowSum
method will have different implementations based on the value ofM
.If
M > 1
, the method does its normal work of comparing the current row's sum with the submatrix's lowest row sum. IfM
is 1, then the method simply returns the sum of the current row, which stops the recursion.