6
votes

Compilation infinie avec modèles

Cette question est juste hors de curiosité. Dans des modèles récursifs Si nous oublions de mettre une spécialisation particulière, le compilateur fera un grand nombre d'itérations, puis arrête de temps en temps et donne une erreur telle que

template<int I>
struct Infinite
{
  enum { value = (I & 0x1)? Infinite<I+1>::value : Infinite<I-1>::value };
};

int main ()
{
  int i = Infinite<1>::value;
}


1 commentaires

Cela se termine dans g ++ 4.8.4 au moins ... Main.cpp: 4: 27: Erreur: la profondeur d'instanciation du modèle dépasse le maximum de 900 (utilisation -ftemplate-profondeur = pour augmenter le maximum) instantifiant 'struct infinie < -899> '


4 Réponses :


2
votes

ne devrait pas être suffisamment intelligent pour s'arrêter à un moment donné?

Comment définissez-vous la phrase "à un moment donné" ? Comment le compilateur voudrait-il savoir votre définition de "à un moment donné" ? Comment savoir quand il doit s'arrêter si vous ne le dites pas explicitement ? Vous devez d'abord le dire en définissant la spécification (s) du modèle de classe sans arrêt (ce que vous avez écrit est un modèle de classe non-stopping).

Dans votre cas, vous devez avoir deux spécialisations du modèle de classe, un dans chaque directions (augmentant et diminuant). Quelque chose comme ceci: xxx


14 commentaires

@Nawaz, en fait, la question est en perspective plus de compilation. Pourquoi ne devrait pas arrêter la compilation à un moment donné, quand il sache que la compilation qui va infini.


@iammilind: Comment cela saurait-il? Aussi, à quel point cela devrait-il arrêter?


@iammilind: "Pourquoi ne devrait-on pas arrêter de s'arrêter à un moment, quand il savait que la compilation se passe infinie." - Il s'est arrêté. Dans votre cas, il s'est arrêté quand il vous a donné l'erreur de compilation.


@iammilind: "Sachez que la compilation va infinie"? En général, "Savoir" que la compilation sera infinie est une tâche extrêmement difficile (ou même insoluble). Le compilateur n'est pas tenu de se préoccuper de telles questions. C'est un problème de Qoui: si le compilateur souhaite passer ses efforts pour capturer de telles situations, cela peut. Mais personne ne l'exige.


En plus de cela, il est très peu probable que la compilation soit infinie dans votre cas. Cela prend simplement une très longue période. Dans tous les cas, il va probablement abandonner éventuellement ou finalement à la suite d'une enveloppe sur le débordement. Vous n'avez tout simplement pas attendu assez longtemps.


@Nawaz, d'abord, je n'ai pas répondu votre réponse :). 2e si vous prenez l'exemple de factorielle, le compilateur s'arrête si vous ne faites pas de spécialisation <1>. ne devrait-il pas arriver dans ce cas aussi.


@iammilind: quel exemple factoriel parle-t-on? La façon dont vous implémentez une récursion non infinie avec des modèles est de définir une spécialisation du modèle général qui ne s'instate pas. Par exemple, Ce factorial <> exemple a la fois le Modèle général qui fait la récursion réelle et un modèle spécialisé qui implémente le boîtier de base.


@iammilind: Non. Ce n'est pas le cas. Même les besoins factoriels Spécialisation . Sans cela, ça ne peut pas arrêter!


@In silico @nawaz, ideone.com/fu0au .. La compilation s'arrête après un jour de temps


@iammilind: Alors, quel est ton point? Je sais déjà que cela doit arrêter parce que nous n'avons pas de machines avec une quantité de mémoire infinte. Si nous avions de telles machines, la récursion ira à jamais à moins que les intrants satisfont à une sorte de cas de base.


@In Silico, exactement c'est mon point. que le code de test ci-dessus n'arrête pas la compilation. Et ça continue, encore et encore


@iammilind: Oui cela s'arrête en donnant une erreur de compilation (faites défiler vers le bas et voir l'erreur). Ce n'est pas un arrêt normal dans le sens que nous parlons tous ici. De plus, une telle arrêt en donnant une erreur se produirait également dans votre code "à un moment donné", vous seuls à attendre assez longtemps.


@iammilind: pas "Peut-être". C'est vrai (je vous garantis: p). Vous devez juste attendre assez longtemps. Peut-être, 20 minutes, 30 minutes, 1 heure ou 2 h ou encore plus!


@Nawaz, true. de toute façon +1 pour les efforts.



2
votes

Le compilateur fait ce que vous le demandez faire. Vous l'avez demandé de vous engager en une récursion infinie - c'est exactement cela. Si vous voulez qu'il "s'arrête à un moment quelconque", vous devez la demander de s'arrêter à "un peu de temps" et de le dire quel spécifique "un peu de temps" vous voulez dire exactement.

La récursion de modèle n'est pas différente de toute autre récursivité dans le programme C ++: Il est de votre responsabilité de spécifier où le résultat de la récursion.


1 commentaires

En d'autres termes, le code de l'OP n'a pas de cas de base. Pour chaque valeur possible de l'entier i Le modèle sera toujours instancier, il sera donc recueil pour toujours (en supposant qu'il existe une quantité infinie de ressources informatiques bien sûr).



6
votes

Obtenir l'analyseur dans une boucle infinie à l'aide de matrice n'est pas nouveau.

// Stresses the compiler infinitely
// from: http://www.fefe.de/c++/c%2b%2b-talk.pdf
template<class T> struct Loop { Loop<T*> operator->(); };
Loop<int> i, j = i->hooray;


0 commentaires

8
votes

Si je comprends votre question correctement, vous voulez que le compilateur reconnaisse qu'elle n'arrêtera jamais itération. En plus de vous arrêter après un nombre fixe de types de nidification, ce que vous voulez est prudemment impossible: si je le vois correctement, vous pouvez exprimer n'importe quel Turing-Machine de cette manière (au moins les modèles en d sont terminés).

Donc, si vous pouvez construire un compilateur qui reconnaît que les types de nids pour toujours avant de tenter réellement de tentative, vous décidez que le Halte Problème indéciable pour les machines à turing.

Cependant, je pourrais très bien vous tromper que vous pouvez mettre tout calcul dans la liste des paramètres (mais la simulation d'une machine de registre semble être possible, car nous pouvons encoder tous les registres dans un paramètre de modèle entier séparé (oui, < Code> int est fini, mais assez grand, ce qui le rend pratiquement illimité)).


0 commentaires