27 fév. 2007

J'ai cassé Visual C++ .Net 2005 Express Edition

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, avril 21 2008, 22:18 par Davidbrcz

Et c'est là qu'on se rend compte que la méta-prog, c'est vraiment archi puissant

2. Le mardi, avril 22 2008, 10:37 par Emmanuel Deloget

Contesterais-tu l'utilité du programme FizzBuzz ? :)

3. Le vendredi, mai 29 2009, 16:34 par buzzyteam

fizzbuzz exists on iphone http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=309389865&mt=8

4. Le lundi, août 24 2009, 01:10 par Emmanuel Deloget

Ah bon ?

C'est pour ça que Visual a planté !

Ajouter un commentaire

Les commentaires peuvent être formatés en utilisant une syntaxe wiki simplifiée.

Fil des commentaires de ce billet