introduction à la metaprogrammation en c++
TRANSCRIPT
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Introduction à la metaprogrammation
Florian Galinier
16 décembre 2014
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
• Du grec µετα (après, au-delà de)• Metalangage : Langage qui permet de décrire un autrelangage, moins abstrait.
• Rendu possible grâce à C++98 et aux templates• Développé grâce à C++11
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Cette écriture abstraite :template <typename T>void f(T i) {
std :: cout <<i<<std :: endl;}
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Correspond à cette écriture concrète :void f(int i) {
std :: cout <<i<<std :: endl;}
void f( float i) {std :: cout <<i<<std :: endl;
}
void f(char i) {std :: cout <<i<<std :: endl;
}
...
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Prenons un exemple un peu plus concret :template <typename T>T my_max (T i,T j) {
return i >=j?i:j;}
Et pour std::string ?
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
string i = "ada";string j = "c";
cout <<my_max (i,j)<<endl;
Et sa sortie :ynigvi@ynigvi - desktop :~/ Meetup -C++/ metaprogrammation$ ./a.outc
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
template <>string my_max ( string i, string j) {
return i.size ()==j.size ()?(i>j?i:j):(i.size ()>j.size ()?i:j);
}
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
string i = "ada";string j = "c";
cout <<my_max (i,j)<<endl;
Et sa sortie :ynigvi@ynigvi - desktop :~/ Meetup -C++/ metaprogrammation$ ./a.outada
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
template <typename T, typename F>struct is_same {
static const bool value = false ;};
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
string i = "ada";
cout <<is_same < decltype (i),int >:: value<<endl;
cout <<is_same < decltype (i),string >:: value<<endl;
Donnera :ynigvi@ynigvi - desktop :~/ Meetup -C++/ metaprogrammation$ ./a.out00
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
template <typename T>struct is_same <T,T> {
static const bool value = true;};
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
string i = "ada";
cout <<is_same < decltype (i),int >:: value<<endl;
cout <<is_same < decltype (i),string >:: value<<endl;
Donnera :ynigvi@ynigvi - desktop :~/ Meetup -C++/ metaprogrammation$ ./a.out01
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Petite devinette
A *b = new B();
cout <<is_same < decltype (*b),B& >:: value<<endl;
Que va-t-il afficher ?
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Réponse
ynigvi@ynigvi - desktop :~/ Meetup -C++/ metaprogrammation$ ./a.out0
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
( defun my_pow (x n)(if (= n 0)
1.0(* x ( my_pow (x (- n 1))))))
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
template <int N>float my_pow ( float x) {
return x * my_pow <N - 1>(x);}
template <>float my_pow <0 >( float x) {
return 1.0;}
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
int main () {float x = my_pow <3 >(3);
}
-> my_pow <3 >(3)-> 3* my_pow <2 >(3)-> 3*3* my_pow <1 >(3)-> 3*3*3* my_pow <0 >(3)-> 3*3*3*1-> 27
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
struct empty_tlist {};
template <typename T, typename S>struct tlist {
T first ;S tail;
};
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Avant C++11
tlist <int ,tlist <double ,tlist <float ,tlist <char , empty_tlist > > > > t;
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
struct empty_tlist {};
template <typename T, typename ... S>struct tlist {
T first ;tlist <S... > tail;
};
template <typename T>struct tlist <T> {
T first ;};
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Depuis C++11
Sans variadique :tlist <int ,tlist <double ,tlist <float ,tlist <char , empty_tlist >>>> t;
Avec variadique :tlist <int ,double ,float ,char , empty_list > t;
AnalysonsAvec les variadiques, nous avons la structure tlist qui estinitialisée avec les paramètres< int, {double, float, char , empty_list} >, qui a pour tête unint et pour queue une tlist paramétrée par< double, float, char , empty_list >, qui est donc construiteselon les paramètres < double, {float, char , empty_list} >, etc.
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Que va afficher ce programme ?class A {public :
void foo () {std :: cout <<"A"<<std :: endl;
};};
class B : virtual public A {public :
void foo () {std :: cout <<"B"<<std :: endl;
};};
int main () {A* a = new B();a->foo ();
}
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Réponse :ynigvi@ynigvi - desktop :~/ Meetup -C++/ metaprogrammation$ ./a.outA
Petite explicationL’héritage de foo étant statique, c’est le type statique de a quiest pris en compte pour l’envoie de message foo.
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Que va afficher ce programme ?class A {public :
virtual void foo () {std :: cout <<"A"<<std :: endl;
};};
class B : virtual public A {public :
void foo () {std :: cout <<"B"<<std :: endl;
};};
int main () {A* a = new B();a->foo ();
}
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Réponse :ynigvi@ynigvi - desktop :~/ Meetup -C++/ metaprogrammation$ ./a.outB
Petite explicationL’héritage de foo est maintenant déclaré comme virtual , c’est àdire dynamique, c’est le type dynamique de a qui est donc prisen compte pour l’envoie de message foo.
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Que va afficher ce programme ?template <typename T>class A_ {public :
void foo () {static_cast <T& >(* this ). foo ();
};};
class A : public A_ <A> {public :
void foo () {std :: cout <<"A"<<std :: endl;
};};
class B : public A_ <B>, public A {public :
void foo () {std :: cout <<"B"<<std :: endl;
};};
int main () {A_ <B> *a = new B();a->foo ();}
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
Réponse :ynigvi@ynigvi - desktop :~/ Meetup -C++/ metaprogrammation$ ./a.outB
Petite explicationComme lors de l’exemple préliminaire, c’est le type statique dea qui est pris en compte, donc de type A_. Mais A_ :: foo()appelle foo de T , le type qui paramétrise la classe A_, c’est àdire B, qui est également le type dynamique de a.
Introduction àla metapro-grammation
FlorianGalinier
Metaquoi ?Introduction tropabstraite
Un exemple plusparlant
Allons un peuplus loinLa spécialisationtotale
La spécialisationpartielle
La récursion
Un ajout deC++11 : Lestemplates variadiques
Un problèmed’héritagePetite questionpréliminaire
Une solution àl’exécution
Une solution à lacompilation
Conclusion
La metaprogrammation en C++ c’est :• avec les templates ;• Turing-complète ;• bien plus encore...
template <typename ... T>void print_loop (tlist <T... > l) {
cout <<l. first ;print_loop (l.tail );
};
template <>void print_loop < empty_list >( tlist < empty_list > l) {
cout <<endl;};
int main () {tlist <char ,char ,char ,char ,char ,char ,char ,char , empty_list >
j = {’M’,’E’,’T’,’A’,’-’,’C’,’+’,’+’ ,{}};print_loop (j);
}