Quelqu'un peut-il m'expliquer pourquoi la première méthode de méta-programmation de modèle va en boucle infinie, mais la seconde fonctionne correctement.
#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
n'est pas une option.constexpr
n'est pas une option. (Il a été introduit en C ++ 11). Cela invalide les réponses existantes. Exxul, veuillez préciser à quelle version C ++ vous êtes limité.Réponses:
Cette ligne provoque l'instanciation des deux
commondivs<N,(M-N)>::val
etcommondivs<(N-M),M>::val
, même si la condition est connue au moment de la compilation et qu'une des branches ne sera jamais prise.Remplacez
? :
parstd::conditional_t
, qui n'a pas cette limitation:la source
Le problème est que tous les opérandes de l'opérateur conditionnel seront évalués, donc les deux
commondivs<N,(M-N)>
etcommondivs<(N-M),M>
obtenir instanciés et leur composants sontval
évalués, puis conduit à l' instanciation de modèle récursif.Vous pouvez appliquer constexpr si et le placer dans une
constexpr
static
fonction membre.VIVRE
la source
::val
doit être générée sur les deux branches bien sûr, mais il s'agit toujours d'une instanciation (d'un modèle avec un membre const statique). L'évaluation au moment de l'exécution ne se produit pas ... eh bien, ce n'est évidemment pas possible car elle ne compile jamais ...L'opérateur ternaire n'est pas comme
if constexpr
: quand un compilateur le voit, il doit générer du code pour les deux branches. En d'autres termes, pour instancier un modèlecommondivs<M, N>
, un compilateur instancie à la fois les modèlescommondivs<N, M - N>
etcommondivs<N - M, M>
.Contrairement à cela,
commondiv(N, M - N)
etcommondiv(N - M, M)
sont traduits en deux appels de fonction. Laquelle est prise, sera décidée lorsque la fonction sera effectivement appelée.Une addition.
HolyBlackCat a donné une solution avec
std::conditional_t
. En voici un autre:la source
Vous obtenez une récursion infinie car:
n'est pas du tout un programme de méta-modèle parce que
?:
, comme le dit @Eng, ce n'est pasconstexpr
.Vous voulez regarder la réponse de @ HolyBlackCat.
la source
?:
ne l'est pasconstexpr
.