Czy ktoś może mi wyjaśnić, dlaczego pierwszy sposób metaprogramowania szablonów prowadzi do nieskończonej pętli, ale drugi działa poprawnie.
#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;
}
constexpr
nie jest opcją.constexpr
nie jest to opcja. (Został wprowadzony w C ++ 11). To unieważnia istniejące odpowiedzi. Exxul, proszę wyjaśnić, do której wersji C ++ jesteś ograniczony.Odpowiedzi:
Ta linia powoduje utworzenie wystąpienia obu
commondivs<N,(M-N)>::val
icommondivs<(N-M),M>::val
nawet jeśli warunek jest znany w czasie kompilacji, a jedna z gałęzi nigdy nie zostanie podjęta.Wymień
? :
sięstd::conditional_t
, które nie mają tego ograniczenia:źródło
Problem polega na tym, że wszystkie argumenty operatora warunkowego zostaną ocenione, więc oba
commondivs<N,(M-N)>
commondivs<(N-M),M>
instancja i instancjaval
zostaną ocenione, a następnie doprowadzą do rekurencyjnej instancji szablonu.Możesz zastosować constexpr if i umieścić go w
constexpr
static
funkcji członka.RELACJA NA ŻYWO
źródło
::val
musi być generowana w obu gałęziach, ale nadal jest to tworzenie instancji (szablonu z elementem stałej stałej). Ocena w czasie wykonywania nie występuje ... cóż, oczywiście nie może, ponieważ nigdy się nie kompiluje ...Operator trójskładnikowy nie jest podobny
if constexpr
: gdy kompilator go zobaczy, musi wygenerować kod dla obu gałęzi. Innymi słowy, w celu utworzenia szablonucommondivs<M, N>
kompilator tworzy zarówno szablony, jakcommondivs<N, M - N>
icommondivs<N - M, M>
.W przeciwieństwie do tego
commondiv(N, M - N)
icommondiv(N - M, M)
są tłumaczone na dwa wywołania funkcji. Który z nich zostanie podjęty, decyzja zostanie podjęta, kiedy funkcja zostanie faktycznie wywołana.Dodanie.
HolyBlackCat dał rozwiązanie
std::conditional_t
. Oto kolejny:źródło
Otrzymujesz nieskończoną rekurencję, ponieważ:
wcale nie jest programowaniem metatemplate, ponieważ
?:
, jak mówi @Eng, nie jestconstexpr
.Chcesz spojrzeć na odpowiedź @ HolyBlackCat.
źródło
?:
nie jestconstexpr
.