• Aucun résultat trouvé

Programmation par Objets en C++

N/A
N/A
Protected

Academic year: 2022

Partager "Programmation par Objets en C++"

Copied!
59
0
0

Texte intégral

(1)

Programmation par Objets en C++

Cl ´ement PERNET

L3-MI, UFR IM2AG, Universit ´e Grenoble Alpes

(2)

Plan du cours

G ´en ´ericit ´e (8-9)

(3)

Plan

G ´en ´ericit ´e (8-9)

Notion de g ´en ´ericit ´e

Classes et fonctions g ´en ´eriques enC++

Specialisation

Meta-Programmation template Traits

SFINAE

(4)

Plan

G ´en ´ericit ´e (8-9)

Notion de g ´en ´ericit ´e

Classes et fonctions g ´en ´eriques enC++

Specialisation

Meta-Programmation template Traits

SFINAE

(5)

G ´en ´ericit ´e

C++ est un langage fortement typ ´e :

les fonctions doivent ˆetre d ´efinies avec desargumentset une valeur de retourayant untype d ´efini;

les classes ont desattributsayant un type d ´efini, les

m ´ethodessont des fonctions comme ci-dessus.

Probl `eme :

I pour des fonctions ayant le m ˆeme traitement, I des classes ayant la m ˆeme structure

avec des types diff ´erents: on doit dupliquer le code

Comment factoriser ce code ? via la g ´en ´ericit ´e

(6)

G ´en ´ericit ´e

C++ est un langage fortement typ ´e :

les fonctions doivent ˆetre d ´efinies avec desargumentset une valeur de retourayant untype d ´efini;

les classes ont desattributsayant un type d ´efini, les

m ´ethodessont des fonctions comme ci-dessus.

Probl `eme :

I pour des fonctions ayant le m ˆeme traitement, I des classes ayant la m ˆeme structure

avec des types diff ´erents: on doit dupliquer le code

Comment factoriser ce code ? via la g ´en ´ericit ´e

(7)

Programmation G ´en ´erique

Programme g ´en ´erique :

Lorsque qu’un m ˆeme code peut ˆetre utilis ´e avec des objets de types variables

Exemple : algo de tri d’objets (entier, chaines de caract `eres, ...)

Deux types de g ´en ´ericit ´e :

I lorsque au sein d’une m ˆeme instance, plusieurs types diff ´erents peuvent ˆetre manipul ´es sous une m ˆeme d ´enomination h ´eritage et polymorphisme

I lorsque le type est inconnu au moment de l’ ´ecriture, mais est fix ´e de fac¸on unique lors de l’instanciation de la classe ou l’appel de la m ´ethode. types param `etr ´es

On parle alors de classes ou de m ´ethodes g ´en ´eriques.

(8)

Plan

G ´en ´ericit ´e (8-9)

Notion de g ´en ´ericit ´e

Classes et fonctions g ´en ´eriques enC++

Specialisation

Meta-Programmation template Traits

SFINAE

(9)

Notion de classe et fonction g ´en ´erique

EnC++,

I les classes et I les fonctions

peuvent ˆetre g ´en ´eriques par rapport `a I une classe ou un type

I une valeur enti `ere

(10)

Notion de classe et fonction g ´en ´erique

d ´eclaration : template< ... >d ´eclarant le param `etre g ´en ´erique pr ´ec `ede la d ´eclaration et la d ´efinition

template <class Truc>

void f(Truc t);

template <class Machin>

class A;

d ´efinition :idem

template <class Type> void f(Type t){...} template <class Machin> class A{ Machin x; };

Instanciation explicite :

A<int> a; f<float> (2.0);

Instanciation implicite : quand le param `etre template peut ˆetre d ´eduit sans ambiguit ´e :

float x = 2.0;

f (x); // Type = float

(11)

Notion de classe et fonction g ´en ´erique

d ´eclaration : template< ... >d ´eclarant le param `etre g ´en ´erique pr ´ec `ede la d ´eclaration et la d ´efinition

template <class Truc>

void f(Truc t);

template <class Machin>

class A;

d ´efinition :idem

template <class Type>

void f(Type t){...}

template <class Machin>

class A{ Machin x; };

Instanciation explicite :

A<int> a; f<float> (2.0);

Instanciation implicite : quand le param `etre template peut ˆetre d ´eduit sans ambiguit ´e :

float x = 2.0;

f (x); // Type = float

(12)

Notion de classe et fonction g ´en ´erique

d ´eclaration : template< ... >d ´eclarant le param `etre g ´en ´erique pr ´ec `ede la d ´eclaration et la d ´efinition

template <class Truc>

void f(Truc t);

template <class Machin>

class A;

d ´efinition :idem

template <class Type>

void f(Type t){...}

template <class Machin>

class A{ Machin x; };

Instanciation explicite :

A<int> a;

f<float> (2.0);

Instanciation implicite : quand le param `etre template peut ˆetre d ´eduit sans ambiguit ´e :

float x = 2.0;

f (x); // Type = float

(13)

Notion de classe et fonction g ´en ´erique

d ´eclaration : template< ... >d ´eclarant le param `etre g ´en ´erique pr ´ec `ede la d ´eclaration et la d ´efinition

template <class Truc>

void f(Truc t);

template <class Machin>

class A;

d ´efinition :idem

template <class Type>

void f(Type t){...}

template <class Machin>

class A{ Machin x; };

Instanciation explicite :

A<int> a;

f<float> (2.0);

Instanciation implicite : quand le param `etre template peut ˆetre d ´eduit sans ambiguit ´e :

float x = 2.0;

f (x); // Type = float

(14)

Notion de classe g ´en ´erique

Exemple

Une fonction max g ´en ´erique

template<typename T>

T max (T a, T b){

return (a < b) ? b : a;

}

// aucun code n’est compil´e, tant que max n’est pas invoqu´e avec // une sp´ecialisation pour T

int main(){

int a=2,b=1;

float x = 2.1;

int c = max<int> (a,b); // max<int> est compil´e pour cet appel

int d = max (c,b); // sp´ecialisation implicite: T=int

float y = max (a,x); // erreur ambiguit´e float y = max (static_cast<float>(a),x); // OK float y = max<float> (a,x); // OK

}

(15)

Notion de classe g ´en ´erique

Exemple

Une classe repr ´esentant des couples d’objets (de m ˆeme type)

#include <iostream>

template<class Type>

class Couple{

private:

Type x, y ; // les deux elements du couple public:

Couple (Type premier, Type second) {x = premier; y = second ;}

void affiche () {

// suppose qu’un Type peut ˆetre pass´e `a un ostream std::cout<< "(" << x <<", " << y << ")" << std::endl;

}

Type getPremier() {return x;}

Type getDeuxieme() {return y;}

};

(16)

Utilisation de la classe g ´en ´erique

I La d ´eclarationtemplatene fait queretarderla connaissance du type g ´en ´erique au moment de l’instanciation.

I A la compilation, il n’y a plus d’inconnue : tous les types g ´en ´eriques sontr ´esolus: on connaˆıt leur instantiation.

I Lors de la d ´eclaration d’un objet de typeCouple, ondoit sp ´ecifier le type effectif correspondant `aType(pas de r ´esolution implicite) :

Couple<int> * ci; Couple<Point> cp;

I On sp ´ecifie aussi le type lors de l’appel au constructeur :

ci = new Couple<int>(27, 43);

I Mais pas pour l’appel :cp.affiche()(la r ´esolution de type a d ´ej `a eu lieu)

(17)

Utilisation de la classe g ´en ´erique

I La d ´eclarationtemplatene fait queretarderla connaissance du type g ´en ´erique au moment de l’instanciation.

I A la compilation, il n’y a plus d’inconnue : tous les types g ´en ´eriques sontr ´esolus: on connaˆıt leur instantiation.

I Lors de la d ´eclaration d’un objet de typeCouple, ondoit sp ´ecifier le type effectif correspondant `aType(pas de r ´esolution implicite) :

Couple<int> * ci;

Couple<Point> cp;

I On sp ´ecifie aussi le type lors de l’appel au constructeur :

ci = new Couple<int>(27, 43);

I Mais pas pour l’appel :cp.affiche()(la r ´esolution de type a d ´ej `a eu lieu)

(18)

Utilisation de la classe g ´en ´erique

I La d ´eclarationtemplatene fait queretarderla connaissance du type g ´en ´erique au moment de l’instanciation.

I A la compilation, il n’y a plus d’inconnue : tous les types g ´en ´eriques sontr ´esolus: on connaˆıt leur instantiation.

I Lors de la d ´eclaration d’un objet de typeCouple, ondoit sp ´ecifier le type effectif correspondant `aType(pas de r ´esolution implicite) :

Couple<int> * ci;

Couple<Point> cp;

I On sp ´ecifie aussi le type lors de l’appel au constructeur :

ci = new Couple<int>(27, 43);

I Mais pas pour l’appel :cp.affiche()(la r ´esolution de type a d ´ej `a eu lieu)

(19)

Plusieurs param `etres de type

#include<iostream>

template <class T, class U>

class Couple{

T x;

U y;

public:

Couple (T premier, U second){x = premier; y = second;}

T getPremier () {return x;}

U getSecond () {return y;}

void affiche () {

// suppose que T et U peuvent ˆetre pass´es `a un ostream std::cout<< x <<", "<< y<<std::endl;

} };

int main(){

int i = 3;

double d = 2.5 ;

Couple<int, double>* c1 = new Couple<int,double>(i,d);

c1->affiche() ;

int j = 4 ;

Couple<int,int>* c2 = new Couple<int,int>(i,j);

c2->affiche() ;

}

(20)

Les types d’arguments template

Les arguments template peuvent ˆetre :

des types ou des classes : template<class T>ou template<typename T>sont ´equivalent des types template :

template<template <class T> class U>

template<class T>

class Tableau{...};

template<template<class T> class Tab>

T somme(Tab<T> tab){ ... }

des nombres entiers : template<int n>

template<int n>

class ArbreNaire{ ... };

I Initialisation par d ´efaut possible : template<class T=float>

(21)

Remarque sur l’instanciation

I Le compilateur ne cherche `a instantier que ce dont il a effectivement besoin.

#include<iostream>

template<class T>

class A{

void f();

void g();

};

template<class T>

A<T>::f(){std::cout<<"coucou")<<std::endl;}

int main() {

A<int> a;

a.f();

}

Ce code compile alors quegn’est pas d ´efinie.

I Instantiation explicite : pour forcer le compilateur `a g ´en ´erer une instance :

template Couple<int,double>; //Force les instanciations de template Couple<float,double>;//ces classes

(22)

Remarque sur l’instanciation

I Le compilateur ne cherche `a instantier que ce dont il a effectivement besoin.

#include<iostream>

template<class T>

class A{

void f();

void g();

};

template<class T>

A<T>::f(){std::cout<<"coucou")<<std::endl;}

int main() {

A<int> a;

a.f();

}

Ce code compile alors quegn’est pas d ´efinie.

I Instantiation explicite : pour forcer le compilateur `a g ´en ´erer une instance :

template Couple<int,double>; //Force les instanciations de template Couple<float,double>;//ces classes

(23)

Le mot cl ´e

typename

Plusieurs significations :

I comme type d’arg. template :template<typename T>

strictrement ´equivalent `aclass

I Pour distinguer lestypesdesvariables

I La g ´en ´ericit ´e template introduit des identificateurs pour les types en plus de ceux pour les variables

I besoin de pr ´eciser au compilateur quand il s’agit de types

template<class T> class CorpsZpZ{

typedef T Element

static const Element one; static const Element zero; };

template<class Corps>

typename Corps::Element add (typename Corps::Element x, typename Corps::Element y){ // suppose que Corps d´efinisse un type Element

return x+y;

}

(24)

Le mot cl ´e

typename

Plusieurs significations :

I comme type d’arg. template :template<typename T>

strictrement ´equivalent `aclass I Pour distinguer lestypesdesvariables

I La g ´en ´ericit ´e template introduit des identificateurs pour les types en plus de ceux pour les variables

I besoin de pr ´eciser au compilateur quand il s’agit de types

template<class T>

class CorpsZpZ{

typedef T Element

static const Element one;

static const Element zero;

};

template<class Corps>

typename Corps::Element add (typename Corps::Element x, typename Corps::Element y){

// suppose que Corps d´efinisse un type Element return x+y;

}

(25)

Inconv ´enients de la g ´en ´ericit ´e template

S ´eparation du code : fronti `ere floue entre d ´eclaration et d ´efinition

I l’int ´egralit ´e du code doit ˆetre disponible au moment de la r ´esolution du param `etre I impossible de compiler un code g ´en ´erique

sans connaˆıtre le type du param `etre toute la d ´efinition doit figurer dans le.h on peut utiliser un.tppinclu par le.h

Compilation multiples du m ˆeme code : car impossible de reposer sur un binaire pr ´e-compil ´e

temps de compilation accru taille des ex ´ecutables accrue

(26)

Inconv ´enients de la g ´en ´ericit ´e template

S ´eparation du code : fronti `ere floue entre d ´eclaration et d ´efinition

I l’int ´egralit ´e du code doit ˆetre disponible au moment de la r ´esolution du param `etre I impossible de compiler un code g ´en ´erique

sans connaˆıtre le type du param `etre toute la d ´efinition doit figurer dans le.h on peut utiliser un.tppinclu par le.h Compilation multiples du m ˆeme code : car impossible de

reposer sur un binaire pr ´e-compil ´e temps de compilation accru taille des ex ´ecutables accrue

(27)

Plan

G ´en ´ericit ´e (8-9)

Notion de g ´en ´ericit ´e

Classes et fonctions g ´en ´eriques enC++

Specialisation

Meta-Programmation template Traits

SFINAE

(28)

Sp ´ecialisation des arguments template

But : donner une impl ´ementation pour une valeur sp ´ecifique du param `etre g ´en ´erique

Comment : template<>

template <class T>

void f (T t){std::cout << "Affichage g´en´erique" << std::endl;}

template<>

void f<int> (int t){

std::cout << "Affichage sp´ecialis´e int: " << t << std::endl; }

// ou par d´eduction implicite du param`etre template template<>

void f (float t){

std::cout << "Affichage sp´ecialis´e float: " << t << std::endl;

}

(29)

Sp ´ecialisation des arguments template

But : donner une impl ´ementation pour une valeur sp ´ecifique du param `etre g ´en ´erique

Comment : template<>

template <class T>

void f (T t){std::cout << "Affichage g´en´erique" << std::endl;}

template<>

void f<int> (int t){

std::cout << "Affichage sp´ecialis´e int: " << t << std::endl;

}

// ou par d´eduction implicite du param`etre template template<>

void f (float t){

std::cout << "Affichage sp´ecialis´e float: " << t << std::endl;

}

(30)

Sp ´ecialisation partielle de classes

Pour les classes : on peut sp ´ecialiser certains des param `etres template.

template<class T, class U, int n>

class A{

};

template <class T, int n>

class A<T, double, n>{

};

template <class T>

class A<T, T*, 2>{

};

Pas forc ´ement une r ´eduction du nombre d’aguments :

template<class E>

class C{ };

template<class E>

class C<E*> { } ; // sp´ecialisation partielle pour un type pointeur vers E

(31)

Specialisation partielle de classes

On peut ne sp ´ecialiser que certaines m ´ethodes d’une classe template :

#include <iostream>

template<class T>

struct A{

T t;

T getT(){return t;}

void affiche(){

std::cout << "classe A g´en´erique" << std::endl;

} };

template<>

void A<int>::affiche(){

std::cout << "classe A sp´ecialis´ee sur int t = " << t

<< std::endl;

}

(32)

Sp ´ecialisation partielle de m ´ethodes ?

Interdite

template<class U,class V>

U f(){V v; U u; ...; return u;}

template<class U>

U f<U,int>(){int v; U u; ...; return u;} //Erreur de compilation

I Sauf si le type template est utilis ´e comme type d’un argument

template<class U, class V>

void f(U u, V v){std::cout<<"generique"<<std::endl;} template<class U, class V>

void f<U,int>(U u, int v){ // Erreur de compilation std::cout<<"sp´ecialisation partielle"<<std::endl; }

template<class U>

void f(U u, int v){ // surcharge -> OK std::cout<<"surcharge"<<std::endl;

}

g ´en ´ericit ´e proche de la surcharge

(33)

Sp ´ecialisation partielle de m ´ethodes ?

Interdite

template<class U,class V>

U f(){V v; U u; ...; return u;}

template<class U>

U f<U,int>(){int v; U u; ...; return u;} //Erreur de compilation

I Sauf si le type template est utilis ´e comme type d’un argument

template<class U, class V>

void f(U u, V v){std::cout<<"generique"<<std::endl;} template<class U, class V>

void f<U,int>(U u, int v){ // Erreur de compilation std::cout<<"sp´ecialisation partielle"<<std::endl; }

template<class U>

void f(U u, int v){ // surcharge -> OK std::cout<<"surcharge"<<std::endl;

}

g ´en ´ericit ´e proche de la surcharge

(34)

Sp ´ecialisation partielle de m ´ethodes ?

Interdite

template<class U,class V>

U f(){V v; U u; ...; return u;}

template<class U>

U f<U,int>(){int v; U u; ...; return u;} //Erreur de compilation

I Sauf si le type template est utilis ´e comme type d’un argument

template<class U, class V>

void f(U u, V v){std::cout<<"generique"<<std::endl;}

template<class U, class V>

void f<U,int>(U u, int v){ // Erreur de compilation std::cout<<"sp´ecialisation partielle"<<std::endl;

}

template<class U>

void f(U u, int v){ // surcharge -> OK std::cout<<"surcharge"<<std::endl;

}

g ´en ´ericit ´e proche de la surcharge

(35)

Sp ´ecialisation partielle de m ´ethodes

I Si le param `etre template n’est pas utilis ´e en argument soit forcer l’utilisation d’arguments (passer un argument inutile)

soit passer par la sp ´ecialisation partielle des classes (via les classes-fonctions)

(36)

Plan

G ´en ´ericit ´e (8-9)

Notion de g ´en ´ericit ´e

Classes et fonctions g ´en ´eriques enC++

Specialisation

Meta-Programmation template Traits

SFINAE

(37)

Meta-Programmation template

Le m ´ecanisme de r ´esolution de la g ´en ´ericit ´e est en fait aussi puissant qu’un langage de programmation :

I r ´ecursivit ´e I tests I boucles I etc

C’est le compilateur qui ex ´ecute ce programme avant de figer le r ´esultat dans le binaire.

le compilateur peut ˆetre pris pour un interpr ´eteur de langage template !

(38)

Meta-programmation template

template<int N>

struct Fibonacci {

static const int val = Fibonacci<N-1>::val + Fibonacci<N-2>::val;

};

template<>

struct Fibonacci<0>{static const int val = 1;};

template<>

struct Fibonacci<1>{static const int val = 1;};

int main(){

std::cout << Fibonacci<8>::val <<std::endl;

}

va g ´en ´erer l’assembleur (g++ -S)

movl $34, %esi

leaq _ZSt4cout(%rip), %rdi call _ZNSolsEi@PLT

(39)

Meta-programmation template

template<int N>

struct Fibonacci {

static const int val = Fibonacci<N-1>::val + Fibonacci<N-2>::val;

};

template<>

struct Fibonacci<0>{static const int val = 1;};

template<>

struct Fibonacci<1>{static const int val = 1;};

int main(){

std::cout << Fibonacci<8>::val <<std::endl;

}

va g ´en ´erer l’assembleur (g++ -S)

movl $34, %esi

leaq _ZSt4cout(%rip), %rdi call _ZNSolsEi@PLT

(40)

Meta-Programmation template

Tests conditionnnels

Isur des variables enti `eres

#include <iostream>

template<int n, int p>

struct equal{constexpr bool val = false;};

template<int n>

struct equal<n,n>{constexpr bool val = true;};

int main(){

if (equal<2,3>::val){ std::cout<<"2=3"<<std::endl;}

if (equal<4,4>::val){ std::cout<<"4=4"<<std::endl;}

}

IMieux : sur des types (le r ˆeve de tout ´etudiant)

#include <iostream> using namespace std; template<class A, class B>

struct equal{static const bool val = false;}; template<class A>

struct equal<A,A>{constexpr bool val = true;}; int main(){

if (equal<int,char>::val){cout<<"int=long"<<endl;} if (equal<long,long>::val){cout<<"long=long"<<endl;}

}

(41)

Meta-Programmation template

Tests conditionnnels

Isur des variables enti `eres

#include <iostream>

template<int n, int p>

struct equal{constexpr bool val = false;};

template<int n>

struct equal<n,n>{constexpr bool val = true;};

int main(){

if (equal<2,3>::val){ std::cout<<"2=3"<<std::endl;}

if (equal<4,4>::val){ std::cout<<"4=4"<<std::endl;}

}

IMieux : sur des types (le r ˆeve de tout ´etudiant)

#include <iostream>

using namespace std;

template<class A, class B>

struct equal{static const bool val = false;};

template<class A>

struct equal<A,A>{constexpr bool val = true;};

int main(){

if (equal<int,char>::val){cout<<"int=long"<<endl;}

if (equal<long,long>::val){cout<<"long=long"<<endl;}

}

(42)

Appart ´e : les expressions constantes

I expressions pouvant ˆetre calcul ´ees `a la compilation via le sp ´ecificateurconstexpr

constexpr double d1 = 2.0/1.0; // OK

constexpr int n = std::numeric_limits<int>::max() ;

Peut aussi s’appliquer aux valeurs de retour de fonctions :

constexpr int factorial(int n){

return n <= 1 ? 1 : (n * factorial(n - 1)); }

template<int n>

struct constN{constN() { std::cout << n << ’\n’; } }; int main(){

std::cout << "4! = " ; constN<factorial(4)> out1;

}

(43)

Appart ´e : les expressions constantes

I expressions pouvant ˆetre calcul ´ees `a la compilation via le sp ´ecificateurconstexpr

constexpr double d1 = 2.0/1.0; // OK

constexpr int n = std::numeric_limits<int>::max() ;

Peut aussi s’appliquer aux valeurs de retour de fonctions :

constexpr int factorial(int n){

return n <= 1 ? 1 : (n * factorial(n - 1));

}

template<int n>

struct constN{constN() { std::cout << n << ’\n’; } };

int main(){

std::cout << "4! = " ; constN<factorial(4)> out1;

}

(44)

Les constantes int ´egrales

C++11 propose des classes pour repr ´esenter des constantes connues `a la compilation

template <class T, T v>

struct integral_constant { // Constant de type T et de valeur v static constexpr T value = v; // stockage de la valeur typedef T value_type; // le type de la valeur typedef integral_constant<T,v> type;// le type de cette classe constexpr operator T() { return v; }// cast pour utilisation

};

Exemple

Factorielle, nouvelle version :

using namespace std; template <unsigned int n>

struct facto : integral_constant<int,n*facto<n-1>::value>{}; template <>

struct facto<0> : integral_constant<int,1> {};

(45)

Les constantes int ´egrales

C++11 propose des classes pour repr ´esenter des constantes connues `a la compilation

template <class T, T v>

struct integral_constant { // Constant de type T et de valeur v static constexpr T value = v; // stockage de la valeur typedef T value_type; // le type de la valeur typedef integral_constant<T,v> type;// le type de cette classe constexpr operator T() { return v; }// cast pour utilisation

};

Exemple

Factorielle, nouvelle version :

using namespace std;

template <unsigned int n>

struct facto : integral_constant<int,n*facto<n-1>::value>{};

template <>

struct facto<0> : integral_constant<int,1> {};

(46)

Les constantes int ´egrales

Cas particulier, les constantes bool ´eennes sont pr ´ed ´efinies :

typedef integral_constant<bool,true> true_type;

typedef integral_constant<bool,false> false_type;

Exemple

Am ´elioration du test d’ ´egalit ´e de classes :

template <class A, class B>

class equal : public std::false_type {};

template <class A>

class equal<A,A> : public std::true_type {};

int main (){

if (equal<int,double>()) // ou equal<int,double>::value std::cout << "int == double" << std::endl;

else

std::cout << "int != double" << std::endl;

}

(47)

Plan

G ´en ´ericit ´e (8-9)

Notion de g ´en ´ericit ´e

Classes et fonctions g ´en ´eriques enC++

Specialisation

Meta-Programmation template Traits

SFINAE

(48)

Les traits

Un trait est une classe template, ne contenant que des typedef, et/ou des constantes connues `a la compilation.

I permettant de donner des informations compl ´ementaires au type de l’argument template

I d’aiguiller des fonctions ou des classes utilisant ce type I `a co ˆut 0 (c’est le compilateur qui travaille)

Exemple

#include <iostream> template <typename T>

struct is_pointer{constexpr bool value = false;}; template <typename T>

struct is_pointer<T*>{constexpr bool value = true;}; int main(){

if (is_pointer<int*>::value){

std::cout<<"je suis un pointeur"<<std:endl; }

}

(49)

Les traits

Un trait est une classe template, ne contenant que des typedef, et/ou des constantes connues `a la compilation.

I permettant de donner des informations compl ´ementaires au type de l’argument template

I d’aiguiller des fonctions ou des classes utilisant ce type I `a co ˆut 0 (c’est le compilateur qui travaille)

Exemple

#include <iostream>

template <typename T>

struct is_pointer{constexpr bool value = false;};

template <typename T>

struct is_pointer<T*>{constexpr bool value = true;};

int main(){

if (is_pointer<int*>::value){

std::cout<<"je suis un pointeur"<<std:endl;

}

}

(50)

Les traits

Utilisation pour compl ´eter l’information d’un type :

template<typename T>

struct type_descriptor{

typedef T type;

typedef T* ptr_t;

typedef T& ref_t;

};

Probl `eme

type_descriptor<int&>::ref_test une ref de ref erreur Sp ´ecialisation

template<typename T>

struct type_descriptor<T&>{ typedef T& type;

...

typedef T& ref_t;

};

(51)

Les traits

Utilisation pour compl ´eter l’information d’un type :

template<typename T>

struct type_descriptor{

typedef T type;

typedef T* ptr_t;

typedef T& ref_t;

};

Probl `eme

type_descriptor<int&>::ref_test une ref de ref erreur

Sp ´ecialisation

template<typename T>

struct type_descriptor<T&>{ typedef T& type;

...

typedef T& ref_t;

};

(52)

Les traits

Utilisation pour compl ´eter l’information d’un type :

template<typename T>

struct type_descriptor{

typedef T type;

typedef T* ptr_t;

typedef T& ref_t;

};

Probl `eme

type_descriptor<int&>::ref_test une ref de ref erreur Sp ´ecialisation

template<typename T>

struct type_descriptor<T&>{

typedef T& type;

...

typedef T& ref_t;

};

(53)

Plan

G ´en ´ericit ´e (8-9)

Notion de g ´en ´ericit ´e

Classes et fonctions g ´en ´eriques enC++

Specialisation

Meta-Programmation template Traits

SFINAE

(54)

SFINAE : Substitution Failure is Not An Error

Lors d’une r ´esolution de param `etre template : I Le compilateur passe en revue les diff ´erentes

sp ´ecialisations disponibles,

I supprime celles qui ne fonctionnent pas, I choisit celle qui est la plus sp ´ecifique

l’ ´echec d’une tentative de substitution n’est pas une erreur Exemple

template<class T>

void f(T a, typename T::type b){} template<class T>

void f(T a, typename T::autre_type b){}

struct A{typedef int type;}; int main(){

f (A(), 42);

// A::autre_type n’existe pas

// -> erreur de compil dans la 2e d´ef de f en faisant T=A // -> signifie juste que cette subst. template est invalide

}

(55)

SFINAE : Substitution Failure is Not An Error

Lors d’une r ´esolution de param `etre template : I Le compilateur passe en revue les diff ´erentes

sp ´ecialisations disponibles,

I supprime celles qui ne fonctionnent pas, I choisit celle qui est la plus sp ´ecifique

l’ ´echec d’une tentative de substitution n’est pas une erreur

Exemple

template<class T>

void f(T a, typename T::type b){} template<class T>

void f(T a, typename T::autre_type b){}

struct A{typedef int type;}; int main(){

f (A(), 42);

// A::autre_type n’existe pas

// -> erreur de compil dans la 2e d´ef de f en faisant T=A // -> signifie juste que cette subst. template est invalide

}

(56)

SFINAE : Substitution Failure is Not An Error

Lors d’une r ´esolution de param `etre template : I Le compilateur passe en revue les diff ´erentes

sp ´ecialisations disponibles,

I supprime celles qui ne fonctionnent pas, I choisit celle qui est la plus sp ´ecifique

l’ ´echec d’une tentative de substitution n’est pas une erreur Exemple

template<class T>

void f(T a, typename T::type b){}

template<class T>

void f(T a, typename T::autre_type b){}

struct A{typedef int type;};

int main(){

f (A(), 42);

// A::autre_type n’existe pas

// -> erreur de compil dans la 2e d´ef de f en faisant T=A // -> signifie juste que cette subst. template est invalide

}

(57)

Application :

std::enable_if

I Permet de provoquer une erreur de type selon une condition bool ´eenne

I Donc de d ´esactiver une sp ´ecialisation (par SFINAE) selon une condition

enable_ifse comporte comme l’impl ´ementation suivante :

template<bool Condition, typename T = void>

struct enable_if{};

template<typename T>

struct enable_if<true, T> {typedef T type;};

I Si la condition est vraie :enable_if<true>::typeest le typeT

I Sinon, il n’existe pas erreur

(58)

Application :

std::enable_if

Utilisation 1 : dans la signature

#include <type_traits>

#include <math.h>

template <class T>

typename std::enable_if <

std::is_floating_point <T>::value,T

>::type modulo (T x, T n){return fmod(x,n);}

template <class T>

typename std::enable_if<std::is_integral<T>::value,T>::type modulo (T x, T n){return x % n;

}

int main(){

int n = modulo (5,3);

float x = modulo (5.0,3.0);

}

(59)

Application :

std::enable_if

Utilisation 2 : comme argument template silencieux

#include <type_traits>

#include <math.h>

using namespace std;

template<class T,

typename U=typename enable_if<

is_integral<T>::value,T

>::type

>

bool estPair (T x){return !(x % 2); }

Références

Documents relatifs

Dans un second temps, vous analyserez les pistes de mise en scène suggérées par quatre des cinq documents iconographiques suivants en vous appuyant sur des

Enfin, vous proposerez à votre équipe un document de travail montrant la manière dont vous allez prendre en compte la question de la mort dans votre mise en scène

Enfin, vous choisirez le document qui se rapproche le plus de votre vision du personnage de Tante Geneviève et formulerez une proposition scénique concrète..

Dans un second temps, vous choisirez le document qui se rapproche le plus de votre vision du personnage du « Poète mort trop tôt » et formulerez une proposition

Les acteurs qui n’ont jamais ressenti cela, qui n’ont pas ete a l’endroit du danger, qui est aussi l’endroit de la plus haute jouissance, passent a côte de ce qui fait

Kenny (Surfacing), Dianora Niccolini, 1982, photographie (tirage argentique, gélatine d’époque), 30x25 cm (environ), collection privée.

DOCUMENT N°5 : Les Trois Grâces de Niki de Saint-Phalle sur Park Avenue, New York DOCUMENT N°6 : Haight Ashbury Hippies,

Ensuite, vous choisirez l’un d’eux pour concevoir votre projet de représentation du palais de Penthée : rapport entre la scène et la salle, choix d’une esthétique, place