La programmation générique avec la STL EIUMLV - Informatique et Réseaux 99 Benoît ROMAND
Ce dont on va parler: Les concepts de généricité : re-encore à nouveau un autre rappel, mais ça finira par rentrer! La Standard Template Library avec les concepts, des exemples, et tout ce qui va bien Enfin:les trucs quil faut comprendre ( ou en tout cas retenir ) pour le projet
Programmation générique: les motivations La principale: la flemme La réutilisation du code ( cf. premier point ) La facilité décriture La lisibilité du code …
The schéma, par Stepanov et Lee Les algorithmes sont indépendants du type de données stockées Il sagit ainsi de connecter des algorithmes à des structures de données, par le biais de connecteurs. AlgorithmesContainers Itérateurs
La STL Application directe des concepts développés par Stepanov Il sagit dune bibliothèque dalgorithmes généraux et de structures de données: Des containers - de séquence - associatifs Des algorithmes - sort, find, search, … - copy, swap, for_each, … Des itérateurs adaptés aux types de container
STL - Les containers de séquence Vector - extensible et relocalisable - accès aléatoire par index en O(1) - insertions et retraits à la fin en O(1) - insertions et retraits lents au milieu List ( liste circulaire doublement chaînée ) - insertions et retraits nimporte où en O(1) - accès au début et à la fin en O(1) - accès lent aux autres éléments Deque ( Double Ended Queue = tampon circulaire dynamique ) - exactement pareil que Vector pour la complexité - pas dinsertion au milieu - bon compromis vitesse daccès / souplesse du remplissage
STL - Les containers associatifs Set ( liste triée ) - Chaque élément doit être unique ( pas de doublons ) - accès aléatoire par clé ( lobjet lui-même est la clé ) Multiset - Un set qui permet les doublons Map ( association clé / élément ) - une clé pour un élément ( pas de doublons ) - accès aléatoire par clé Mulimap - Un map ou les éléments peuvent être multiples pour une clé
STL – Les itérateurs L'itérateur est une généralisation des pointeurs.. Il permet de parcourir en séquence les éléments d'un conteneur. Hiérarchie des itérateurs: EcritureLecture Forward Bidirectionnel Accès aléatoire It+n, It-n It++, It-- It++
STL – petits exemples (1) La copie void main() { list l(4,0); // l vaut 0::0::0::0::[] vector v(10,1); // v vaut [1,1,1,1,1,1,1,1,1,1,1] vector ::iterator i = copy(l.begin(),l.end(),v.begin()); copy(v.begin(),i, ostream_iterator (cout," ")); copy(i,v.end(), ostream_iterator (cout," ")); }
STL – petits exemples (2) Le tri #include List initC(char*c) { List majax; while (*c != \0= majax.push_back(*c++); return majax; } void main() { List gerard = initC("le plus grand et le plus fort des magiciens"); gerard.sort(); gerard.unique(); for (List ::iterator i = gerard.begin() ; i != gerard.end() ; i++) cout << *i; }
STL – Autre notion : ladaptateur (1) Adaptateur de container Pour résumer : Adaptateur > Stack ( la pile ) Peut être implémentée avec Vector, List, Deque Principe LIFO : push et pop à la même extrémité Queue ( la file ) Peut être implémentée avec List, Deque Principe FIFO Priority_queue ( la file par priorité ) Dépend dune fonction de comparaison: priority_queue, fcomp >
STL – Autre notion : ladaptateur (2) void main() { int arr[] = {1,4,9,16,25}; list liste(arr, arr+5); list ::reverse_iterator revit; revit = liste.rbegin(); while (revit != liste.rend()) cout << *revit++; } Adaptateurs ditérateursAdaptateurs ditérateurs Litérateur inverseLitérateur inverse
STL – Autre notion : ladaptateur (3) void main() { int t1[] = { 1, 3, 5, 7, 9}; deque dq1(t1,t1+5); int t2[] = { 2, 4, 6}; deque dq2(t2,t2+3); copy(dq1.begin(), dq1.end(), back_inserter(dq2)); for (int i=0 ; i<dq2.size() ; i++) cout << dq2[i] << ; } Litérateur dinsertionLitérateur dinsertion
STL – pour finir : les foncteurs Abstraction de la notion de fonction. Foncteur = Objet dont la classe définit lopérateur (), appelé opérateur de fonction Permettent dappliquer des fonctions sur les objets manipulés #include template T applique(T i, T j, F foncteur) { return foncteur(i, j); } void main(void) { plus foncteur_plus; cout << applique(2, 3, foncteur_plus) << endl; }
La suite sur le site Web …
Parlons voir de Ookce… 1 : les concepts de généricité ne sappliquent pas seulement au c++… 2 : on a le droit de les appliquer 3 : le joli schéma de Stepanov peut être généralisé : on sait à quoi ressemble lobjet avec lequel on veut discuter et ce quil doit faire, mais on ne sait pas comment il fait ce quil fait ( et on plus ce nest pas notre problème ) En gros, si lobjet cible change, on lui demande simplement de garder la même apparence. Comme ça, on na pas besoin de recommencer tout notre code 4 : cest très chiant au début, mais ça facilite la vie après