J'ai cassé Visual C++ .Net 2005 Express Edition
Par Emmanuel Deloget, mardi 27 février 2007 à 18:00 :: Expériences :: permalien #56
Des fois, il ne faut pas trop demander à nos outils. Lorsque je suis tombé sur de billet de The Coding Horror, qui nous éclaire sur les difficultés que peuvent rencontrer certain managers lorsqu'ils cherchent des programmeurs sachant programmer (visiblement, ils sont loin de représenter la majorité des programmeurs), je me suis dit, "moi aussi je veux coder mon propre FizzBuzz !"
FizzBuzz est un programme d'une utilité relative. Pour chaque valeur de 0 à 100, il affiche Fizz si la valeur est divisible par 3, Buzz si la valeur est divisible par 5, FizzBuzz si la valeur est divisible par 3 et par 5, et la valeur dans les autres cas.
Quite à le faire, autant le faire bien. Foin de tests ridicules et de boucles trop lisible - utilisons les techniques de méta-programmation (que vous commencez à connaître, hein ?).
Alors me voici, me lançant dans l'écriture d'un programme stupide[1]. Attention, ça peut faire mal aux yeux.
#include <iostream>
template <int n, int m3, int m5> struct fizzbuzz : fizzbuzz<n-1, (n-1)%3, (n-1)%5> { fizzbuzz() { std::cout << n << std::endl; } };
template <int n> struct fizzbuzz<n, 0, 0> : fizzbuzz<n-1, (n-1)%3, (n-1)%5> { fizzbuzz() { std::cout << "FizzBuzz" << std::endl; } };
template <int n, int p> struct fizzbuzz<n, 0, p> : fizzbuzz<n-1, (n-1)%3, (n-1)%5> { fizzbuzz() { std::cout << "Fizz" << std::endl; } };
template <int n, int p> struct fizzbuzz<n, p, 0> : fizzbuzz<n-1, (n-1)%3, (n-1)%5> { fizzbuzz() { std::cout << "Buzz" << std::endl; } };
template <> struct fizzbuzz<0,0,0> { fizzbuzz() { std::cout << 0 << std::endl; } };
template <int n> struct fb_run { fizzbuzz<n, n%3, n%5> fb; };
int main() { fb_run<7> fb; }
Comment ça marche ? C'est simple: l'instanciation de fb_run<N> instancie un objet fizzbuzz<N, N%3, N%5>, qui dérive de fizzbuzz<(N-1), (N-1)%3, (N-1)%5>, etc, jusqu'à fizzbuzz<0, 0, 0>. Les constructeurs fizzbuzz sont appelés en cascade (en commençant l'ancêtre le plus éloigné, donc fizzbuzz<0, 0, 0>). Lorsque n%3==0, c'est la spécialisation partielle fizzbuzz<n, 0, p> qui est utilisée (le principe est similaire pour les deux autres spécialisations partielles).
Au final, on devrait voir écrit 0, 1, 2, Fizz, 4, Buzz, Fizz, 7
.
Sauf que le compilateur est perdu, et génère une erreur du type fatal error C1001: An internal error has occurred in the compiler. (compiler file 'msc1.cpp', line 1393).
Bien sûr, réécrire le code en utilisant la composition plutôt que l'héritage corrige le problème. En attendant, il y a quand même un problème sur le compilateur de Microsoft. On peut vraiment compter sur personne...
Notes
[1] difficile de savoir si "stupide" s'accorde avec "programme" ou avec "écriture"...
Commentaires
1. Le lundi 21 avril 2008 à 22:18, par Davidbrcz
2. Le mardi 22 avril 2008 à 10:37, par Emmanuel Deloget
:: Fil rss des commentaires de ce billet ::
Ajouter un commentaire