1 Les templates

1.1 Présentation

Les templates sont la solution retenue en C++ pour permettre la généricité. En effet, il est courant dans un programme de construire des listes, des tableaux, etc. de données de différents types. Sans généricité, il est fastidieux de construire ces ensembles. En effet, si on veut une liste de doubles, une liste d'entiers, et une liste de chaînes de caractères, il sera nécessaire d'implémenter le fonctionnement de 3 listes différentes, et de manipuler autant de types de données (liste entiers, liste doubles, etc.). La généricité, et donc les templates, répond à ce problème en permettant de créer des classes dont le type de certains membres sont paramétrables.

Les templates peuvent s'appliquer directement à une classe, ou à une fonction. Schématiquement, le code est dupliqué avec les différents types utilisées avant d'être compilé. Pour être utilisées, les templates reposent sur une syntaxe pour les déclarer, et une syntaxe pour les utiliser.

template <typename T> // de préférence
// ou
template <class T>
// puis, élément sur lequel le template s'applique :
class A {
    T _member;
    // ...
};
// ou
int do_something(const T &obj) { // ...

// Sur classe :
A<int> objet_a;
// Sur fonction :
int res = do_something<double>(42.0);

En raison de la façon de passer du code générique au programme réel, il n'est pas possible de procéder à de la compilation séparée quand on utilise les templates. On écrira donc le code générique dans un seul fichier, par convention suffixé .hpp, qui sera ensuite inclus par ses utilisateurs et compilé en même temps qu'eux.

1.2 Application

Cet exercice consistera à implémenter un conteneur dynamique similaire au std::vector simplifié. Nous le nommerons vecteur. Notre conteneur est paramétrable (il peut contenir n'importe quel type de donnée) grâce à un template. Il gère ses données avec 3 attributs :

Ces attributs sont gérés de la manière suivante : à la construction du vecteur, la taille allouée est de 4. Une fois les 4 éléments affectés, en cas de nouvelle insertion, on double la taille du vecteur. Pour cela, il est nécessaire d'allouer un nouveau tableau, d'y recopier les éléments de l'ancien, puis d'échanger les valeurs des pointeurs (content va donc pointer sur le nouveau tableau), et enfin de supprimer l'ancien tableau. Évidemment, memory_allocated est mise à jour pour refléter la nouvelle taille du tableau.

Les méthodes de la classe vecteur sont les suivantes :