Vous êtes sur la page 1sur 26

Ecole Nationale Supérieure de Techniques Avancées

Programmation Scientifique en C++


SIM 201 Chapitre V

Programmation générique

E. Lunéville

2022
« meta » programmation

Fonction partie positive


version entière version réelle

autant de versions que de types considérés !

Le C++ offre un mécanisme de généralisation : template

version générique
modèle de fonction avec un type abstrait T
T est substituable par tout type y compris
des classes
Les opérations doivent être compatibles
avec le type substitué : T(0), <T(0 ), =T(0)

SIM201– Chapitre 5 1
« meta » programmation

Mécanisme géré par le compilateur :


 cherche positif(int)
 trouve template positif(T)
 substitue T par int et génère à la volée :
 compile à la volée cette version int
 idem pour positif(double)

- méthode par substitution , ne relève pas strictement du langage


- si la fonction n’est pas invoquée elle n’est pas compilée
il peut donc rester des erreurs même si le compilateur n’en signale pas !

SIM201– Chapitre 5 2
Programmation générique

 Extension du concept aux classes


 Programmation efficace, robuste (version unique de code)
 Mécanisme d’abstraction très puissant
 Mise en œuvre parfois complexe
 Instanciation de code (sensibilité aux compilateurs)
 Largement utilisé, en particulier par la STL (Standard Template Library)

Plan
 Programmation générique des fonctions
 Programmation générique des classes
 Spécialisation partielle ou totale
 Mécanismes de compilation
 Un exemple complet : la classe complex de la STL

SIM201– Chapitre 5 3
Modèles de fonction
Syntaxe générale d’une fonction modèle

Les types abstraits T1,T2,... doivent tous intervenir dans la liste des arguments
entrée/sortie sous forme primaire ou dérivée (pointeur, référence)

j=2 erreur compilation


j=97 c=‘a’

char se convertit en int (code ASCII) ne peut pas deviner le type T (arg retour)
il faut l’expliciter le type T : fonc<char>

SIM201– Chapitre 5 4
Modèles de fonction

3.5 (T1=double, T2=int)


3 (T1=int, T2=double)

Il faut expliciter T1

Syntaxes équivalentes
typename séparé

class à la place
de typename
SIM201– Chapitre 5 5
Une fonction min générale

opérateur ternaire c ? v : f

fonctionne avec tout type supportant l’opérateur <

Min avec des types différents

Suppose un transtypage « consistant » du type T2 vers le type T1


peu conseillé, ici :
Min(2.5,3)=2.5 et Min(3,2.5)=2
SIM201– Chapitre 5 6
Classe modèle

Généralisation du concept aux classes :

les types abstraits T1,T2,... doivent tous intervenir


dans la définition de la classe

version explicite double

pointeur de type T

constructeur

op. d’accès

SIM201– Chapitre 5 7
Classe modèle : instanciation d’un objet

Instanciation d’un objet de la classe modèle Vect

objet Vect avec T=double

objet Vect avec T=char*

instanciation explicite <double>, <char *>

A la compilation :
 recherche le type Vect<double>
 trouve template <typename T> class Vect
 génère le code explicite en remplaçant T par double
 compile le code généré
 recherche le constructeur Vect<double>(int)
type composé : Vect< Vect<double> > pour un vecteur de vecteurs (matrice)

SIM201– Chapitre 5 8
Classe modèle : fonctionnalités

La programmation générique est une technique d’abstraction permettant de


manipuler des objets complexes en se focalisant sur les opérations de
structure
Définition des opérations de structure ? Par exemple, l’addition de vecteurs

U+=V

+= doit fonctionner pour le type T, quelque soit sa signification


+= ne fonctionne pas pour le type char * (pointeur), plus de Vect<char *> !

Plus il y a de fonctionnalités, moins la classe sera abstraite !


la classe vector de la STL ne propose pas les opérations algébriques
pour conserver un haut niveau d’abstraction

SIM201– Chapitre 5 9
Fonction membre modèle

Il peut exister des fonctions modèle dans une classe modèle


par exemple : produit par un scalaire quelconque d'un Vect (numérique)

S type abstrait spécifique


à l’opérateur *=
T*=S doit être possible

plus général que Vect<T>& operator*=(const T & s)

peut poser des problèmes, cas classique :


erreur de compilation
double*=complex<double> impossible
même si on ne passe pas dans le cas
complexe !

SIM201– Chapitre 5 10
Spécialisation d’une fonction modèle

Dans certaines situations, il est nécessaire de proposer des


versions particulières d’une fonction ou d’une classe modèle
on parle de spécialisation du modèle

générique

spécialisation partielle

spécialisation totale 1.414


4
chainechaine

SIM201– Chapitre 5 11
Spécialisation d’une fonction membre

Dans une classe modèle, il est possible de spécialiser des


fonctions membres

spécialisation d’une fonction membre


d’une classe modèle

Spécialisation totale d’une fonction membre modèle d’une classe modèle

SIM201– Chapitre 5 12
Spécialisation d’une classe modèle

Même principe pour une classe modèle

générique

spécialisation partielle

spécialisation totale

Les syntaxes de spécialisation peuvent varier d’un compilateur à l’autre …


Il existe une multitude de variantes de spécialisation, voir documentation

Programmation assez complexe, niveau avancé en C++

SIM201– Chapitre 5 13
Programmation séparée et template

Implémentation dissociée de la définition (syntaxe)


 Pour les fonctions modèle même syntaxe que la déclaration

 Pour les fonctions membre d'une classe modèle :

 Pour les fonctions membre modèle d'une classe modèle :

les modèles de la classe et ceux de la


fonction sont dans 2 template distincts !
SIM201– Chapitre 5 14
Programmation séparée et template

vecteur.h vecteur.cpp

SIM201– Chapitre 5 15
Programmation séparée et template

Principe de l’implémentation /compilation séparée :

main.cpp vecteur.hpp vecteur.cpp

 Compilation de vecteur.cpp et main.cpp (génère vecteur.o et main.o)


 Edition de lien des fichiers objets vecteur.o et main.o (génère l’exécutable)
 Rappel : un fichier d’entête (.hpp) ne se compile pas …

Ne fonctionne pas avec des template !!!


 la compilation de vecteur.cpp ne produit rien (paramètre T non connu)
 compilation de main.cpp ?
 Trouve la définition de vect<T> dans vecteur.hpp, remplace T par double
 Mais ne compile pas vecteur.cpp avec T=double (ne le connaît pas)

Comment faire ?
SIM201– Chapitre 5 16
Programmation séparée et template

 Première méthode : tout mettre dans le fichier d’entête

main.cpp vecteur.hpp

déclaration

implémentation

compilation de main.cpp :
 trouve la définition de vect<double> dans vecteur.hpp (T=double)
 compile l’implémentation de vect avec T=double qui s’y trouve !

Inconvénient : peut multiplier les versions compilées de vect<T>


pas très gênant pour les petits codes

SIM201– Chapitre 5 17
Programmation séparée et template

 Deuxième méthode : inclure le fichier d’implémentation

ne pas inclure vecteur.h

main.cpp vecteur.cpp

vecteur.hpp

 compilation de main.cpp : décocher les cases


même chose que la première méthode
 même inconvénient que la première
méthode
 attention dans CodeBlocks :
ne pas compiler vecteur.cpp

SIM201– Chapitre 5 18
Programmation séparée et template

 Troisième méthode : instanciation explicite

implémentation
main.cpp vecteur.hpp vecteur.tem
non compilé

Instanciation explicite de type


seuls ces types pourront être utilisés

vecteur.cpp compilé

Compilation de vecteur.cpp :
génère les versions double et float avec une seule version
main.cpp pourra les trouver à l’édition de lien

limite l’utilisation de la classe Vect au type double et float

SIM201– Chapitre 5 19
Programmation séparée et template

 Autres méthodes

 Certains compilateurs proposent des méthodes « maison »


voir leur documentation, méthodes non portables

 mot clé export


la norme C++ propose le mot clé export pour gérer ces problèmes
un seul compilateur (payant Commeau) l’a implémenté !!!
lors d’une réunion de normalisation , il a été demandé de retirer export de la
norme, sans succès … A été "retiré" depuis c++11

En résumé : utiliser la première (ou seconde) méthode


 la plus simple, la plus portable (technique utilisée par la STL)
 expose le code (problème pour les fabricants de logiciels)

SIM201– Chapitre 5 20
Exemple : la classe complex de la STL

classe complex définie dans le header <complex>


robuste et complète …

données privées

fonctions membres

SIM201– Chapitre 5 21
Exemple : la classe complex de la STL

Opérateurs algébriques (externes)

SIM201– Chapitre 5 22
Exemple : la classe complex de la STL

Opérateurs de comparaison et flux

SIM201– Chapitre 5 23
Exemple : la classe complex de la STL

Fonctions transcendantes

SIM201– Chapitre 5 24
Conclusion

 Modèle de fonctions et de classe


 Ne satisfait pas au paradigme de l'implémentation séparée
 Mécanisme puissant d'abstraction
 Assez facile à mettre en œuvre (hormis spécialisation)
 Largement utilisé par la STL et la communauté

SIM201– Chapitre 5 25

Vous aimerez peut-être aussi