Generics en C++ : pourquoi en a-t-on besoin et comment les utiliser en pratique

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : que sont les generics en C++ et pourquoi en a-t-on besoin

Dans le monde de la programmation moderne, la réutilisation du code est l'un des principes clés. Si vous écrivez une fonction de sommation pour int, puis pour double et float, tôt ou tard vous voudrez éviter la duplication. C'est là que les generics (programmation générique) viennent à la rescousse. En C++, ce concept est implémenté via les modèles (templates).

Les generics permettent d'écrire du code qui fonctionne avec n'importe quel type de données, sans sacrifier les performances (contrairement aux fonctions virtuelles ou à void*). Le compilateur génère une version distincte de la fonction ou de la classe pour chaque type spécifique, ce qui offre une vitesse d'exécution maximale.

Dans cet article, nous verrons pourquoi les generics sont nécessaires en C++, comment les déclarer et les utiliser correctement en pratique, ainsi que les erreurs typiques et les techniques avancées.



Bases de la syntaxe : comment déclarer et utiliser un modèle

Un modèle en C++ se déclare avec le mot-clé template et des chevrons <>, à l'intérieur desquels on spécifie le paramètre de type (généralement typename ou class).

Fonction modèle

L'exemple le plus simple est une fonction qui retourne le maximum de deux valeurs :

template <typename T>T max(T a, T b) {    return (a > b) ? a : b;}

// Utilisation :int main() { std::cout << max(3, 7) << std::endl; // 7 std::cout << max(3.14, 2.71) << std::endl; // 3.14 std::cout << max('a', 'z') << std::endl; // z return 0;}

Remarque : le compilateur déduit automatiquement le type T en fonction des arguments passés. Si vous devez spécifier explicitement le type, vous pouvez écrire max<double>(3.14, 2.71).



Classe modèle

Les modèles fonctionnent également avec les classes. Un exemple classique est un conteneur simple « paire » :

template <typename T1, typename T2>class Pair {private:    T1 first;    T2 second;public:    Pair(T1 f, T2 s) : first(f), second(s) {}    T1 getFirst() const { return first; }    T2 getSecond() const { return second; }};

// Utilisation :Pair<int, std::string> student(1, "Alice");std::cout << student.getFirst() << " " << student.getSecond();

Ici, T1 et T2 sont des paramètres de modèle qui peuvent être de n'importe quel type.



Exemples pratiques : des conteneurs simples aux algorithmes

Examinons plusieurs scénarios réels où les generics sont indispensables.



Tri universel

Écrivons une fonction modèle de tri de tableau pour tout type supportant l'opérateur < :

template <typename T>void bubbleSort(T arr[], int n) {    for (int i = 0; i < n - 1; ++i)        for (int j = 0; j < n - i - 1; ++j)            if (arr[j] > arr[j + 1])                std::swap(arr[j], arr[j + 1]);}

// Exemple :int intArr[] = {5, 2, 8, 1};bubbleSort(intArr, 4); // Fonctionne avec int

double dblArr[] = {3.14, 2.71, 1.41};bubbleSort(dblArr, 3); // Fonctionne avec double


Pile avec type de données arbitraire

Implémentons une pile simple basée sur un modèle :

template <typename T>class Stack {private:    std::vector<T> elements;public:    void push(const T& value) { elements.push_back(value); }    void pop() { if (!elements.empty()) elements.pop_back(); }    T top() const { return elements.back(); }    bool empty() const { return elements.empty(); }};

// Utilisation :Stack<int> intStack;intStack.push(10);intStack.push(20);std::cout << intStack.top(); // 20


Algorithme « trouver et remplacer »

Fonction modèle qui remplace toutes les occurrences d'une valeur par une autre dans un conteneur :

templa                

Blogs

Book Recommendations