introduction à la metaprogrammation en c++

28
Introduction à la metapro- grammation Florian Galinier Metaquoi ? Introduction trop abstraite Un exemple plus parlant Allons un peu plus loin La spécialisation totale La spécialisation partielle La récursion Un ajout de C++11 : Les templates variadiques Un problème d’héritage Petite question préliminaire Une solution à l’exécution Une solution à la compilation Conclusion Introduction à la metaprogrammation Florian Galinier 16 décembre 2014

Upload: galinierf

Post on 16-Jul-2015

123 views

Category:

Software


0 download

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);

}