Chapitre 3 Métaprogrammation Statique
Chapitre 3 Métaprogrammation Statique
Chapitre 3 Métaprogrammation Statique
Habituellement templates sont utilisés pour écrire des fonctions et classes acceptant
plusieurs types, qui engendre une économie de temps et de réécriture. Mais ils
peuvent etre utilisés en meta-programmation :
// Ici, x vaudra 24 avant même que vous ne lanciez votre programme - coût à
l'exécution : 0 sesterce
unsigned int x = Fact<4>::Value;
la syntaxe de la meta-programmation est un peu particulière, pleine de
spécialisations et d'enum comme vous n'avez pas l'habitude d'en voir. Nous allons
donc voir quelques règles de base de cette syntaxe un peu particulière. :
3.1. Quelques règles de meta-programmation
Comme tout type de programmation, la meta-programmation se base sur certaines
règles et une certaine syntaxe. La règle de base est que tout doit toujours rester au
maximum connu du compilateur. Si vous introduisez du code ne pouvant être évalué
qu'à l'exécution, soit votre meta-programme est cassé et le compilateur ne se gêne
pas pour vous le faire remarquer, soit c'est voulu (on ne peut pas toujours tout
précalculer), et dans ce cas cela s'en ressentira sur l'exécution du programme. Il faut
donc suivre assez rigoureusement certains principes de base,
// La même en meta-programme
template<int N> struct Identite
{
enum {Value = N;}
};
unsigned int x = Identite<5>::Value; // la valeur de x est connue de notre compilateur
};
Maintenant, nous voulons évaluez 11! :
Code :
Code :
// Code habituel
if (Condition)
DoSomething();
else
DoSomethingElse();
// Méthode habituelle
for (int i = 5; i < 15; ++i)
DoSomething();
Exemple
for(int i=0;i<100000;i++) tab[i] = 2*i+1;
engendre 100000 tests et retours et affectations
1. for(int i=0;i<50000;i++)
2. {
3. tab[2*i] = 2*(2*i)+1;
4. tab[2*i+1] = 2*(2*i+1)+1;
}
avec ce code la boucle engendre 50000 tests et retours
et 100000 affectations
1. // fonction de base
2. template<int N> void remplir( int* tab )
3. {
4. tab[N] = 2*N+1;
5. remplir<N-1>(tab);
6. }
7.
8. // fonction de terminaison
9. template<> void remplir<0>( int* tab )
10. {
11. tab[0] = 1;
Code :
1. remplir<99>(tab);
1. tab[99] = 199;
2. tab[98] = 197;
3. tab[97] = 195;
4. ...
5. tab[2] = 5;
6. tab[1] = 3;
7. tab[0] = 1;
Gain de vitesse notable (proche du x2 ou du x3) mas evidemment perte sur la taille
de l'executable.
La factorielle
La puissance
L'exponentielle
Le cosinus