Modèles et typage en C++ : des génériques aux concepts

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

Generics et typage en C++ : pourquoi ce n'est pas « juste des modèles » ?



Lorsqu'un développeur passe de Python ou Java à C++, le mot « modèle » (template) lui fait souvent peur. Des associations avec des chevrons infinis, des erreurs de compilation incompréhensibles et la magie de std::vector<int> lui viennent à l'esprit. En réalité, les generics en C++ (ou programmation générique) sont un outil extrêmement puissant qui permet d'écrire du code une seule fois et de l'utiliser avec n'importe quel type de données. Et oui, ce n'est pas du tout la même chose que les génériques en Java ou C#.



Dans cet article, nous allons voir comment fonctionne le typage en C++ via les modèles, en quoi les modèles de classes diffèrent des modèles de fonctions, et pourquoi les concepts ont été ajoutés en C++20. Il y aura beaucoup d'exemples – des plus simples à ceux qui seront réellement utiles en production. C'est parti !



Que sont les generics (modèles) en C++ ?



Pour faire simple : les modèles en C++ sont une façon d'écrire du code qui fonctionne avec n'importe quel type de données, sans perdre en performance. Contrairement au typage dynamique de Python, où le type est vérifié à l'exécution, C++ génère une version distincte de la fonction ou de la classe pour chaque type utilisé lors de la compilation. Cela s'appelle le typage statique avec paramétrisation.



Syntaxiquement, un modèle se déclare avec le mot-clé template et des chevrons contenant les paramètres :



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


Ici, typename T est le paramètre du modèle. Vous pouvez utiliser class à la place de typename – il n'y a pas de différence. Lorsque vous écrivez max(3, 7), le compilateur substitue automatiquement int à T et crée la fonction int max(int, int). Si vous écrivez max(3.14, 2.71) – vous obtenez une version pour double. Simple et efficace.



Modèles de fonctions : premier pas vers les generics



Commençons par le plus simple – les modèles de fonctions en C++. C'est un moyen idéal d'éviter la duplication de code lorsque la logique est identique mais que les types sont différents.



Exemple : une fonction qui affiche un élément dans la console (utile pour le débogage) :



#include <iostream>#include <string>

template <typename T>void print(const T& value) { std::cout << value << std::endl;}

int main() { print(42); // int print(3.1415); // double print("Hello"); // const char* print(std::string("Generics!")); // std::string return 0;}


Remarquez : nous utilisons const T& – c'est du typage en C++ avec passage par référence constante, pour éviter la copie des gros objets. Pour les types natifs (int, double), ce n'est pas critique, mais c'est une bonne habitude.



Et si on doit passer deux arguments de types différents ? Facile :



template <typename T1, typename T2>auto add(T1 a, T2 b) -> decltype(a + b) {    return a + b;}

// En C++14 et plus récent, on peut simplement :template <typename T1, typename T2>auto add(T1 a, T2 b) { return a + b;}


Ici, auto déduit automatiquement le type de retour. C'est ça, les generics en action – un seul code, une infinité de combinaisons de types.



Modèles de classes : construire des structures universelles



Passons maintenant aux modèles de classes en C++. C'est la base de la bibliothèque standard (STL) : std::vector<T>, std::map<Key, Value>, std::optional<T> – tous sont implémentés via des modèles.



Écrivons un exemple simple mais parlant – une classe modèle « Paire » (analogue à std::pair) :



template <typename First, typename Second>class Pair {private:    First first_;    Second second_;public:                

Blogs

Book Recommendations