Can somebody explain to me, why the first call using the template function is falling into an infinite loop, while the second compile-time function runs correctly?
#include <iostream> using namespace std; template<int N, int M> struct commondivs { static const int val = (N<M) ? commondivs<N,(M-N)>::val : commondivs<(N-M),M>::val; }; template<int N> struct commondivs<N,N> { static const int val = N; }; int commondiv(int N, int M){ if(N==M){ return N; } return (N<M)?commondiv(N,(M-N)):commondiv((N-M),M); } int main() { cout << commondivs<9,6>::val << endl; cout << commondiv(9,6) << endl; return 0; }
(N<M) ? commondivs<N,(M-N)>::val : commondivs<(N-M),M>::val
This line causes instantiation of both commondivs<N,(M-N)>::val
and commondivs<(N-M),M>::val
, even if the condition is known at compile time and one of the branches will never be taken.
Replace ? :
with std::conditional_t
, which doesn't have this limitation:
static const int val = std::conditional_t<N < M, commondivs<N,(M-N)>, commondivs<(N-M),M>>::val;
The problem is all the operands of conditional operator will be evaluated, so both commondivs<N,(M-N)>
and commondivs<(N-M),M>
get instantiated and their val
get evaluated and then leads to recursive template instantiation.
You can apply constexpr if and put it in a constexpr
static
member function.
If the value is
true
, then statement-false is discarded (if present), otherwise, statement-true is discarded.
template<int N, int M> struct commondivs { constexpr static int get_val() { if constexpr (N<M) return commondivs<N,(M-N)>::val; // if true, the else part won't be evaluated else return commondivs<(N-M),M>::val; // vice versa } static const int val = get_val(); };
LIVE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With