Loading lang_cpp_03_generic...

enib_small.png LANG-CPP 03_Generic — Programmation générique

Bien que ce n'ait pas été explicitement précisé jusqu'alors, les précédents chapitres ont déjà fait usage de fonctionnalités génériques :
Si nous nous sommes contentés d'un usage minimal de ces fonctionnalités, ce n'était que pour aborder progressivement la variété de nouvelles notions que C++ introduit.
Toutefois, le langage C++, et à plus forte raison sa déclinaison moderne, encourage très vivement à utiliser le plus possible les fonctionnalités génériques.
{1 #function } Les fonctions génériques
{2 #iter } Les itérateurs
{3 #containers } Les conteneurs génériques
{4 #type } Réalisation d'un type générique

Une vision simplifiée, mais néanmoins suffisante dans la plupart des usages courants, des fonctionnalités génériques (template) consiste à les considérer comme une simple substitution lexicale des noms de types dans le code source.
Elles peuvent être considérées comme des solutions qui sont invoquées par défaut lorsque aucune fonctionnalité n'existe plus spécifiquement pour les types effectivements utilisés.

La bibliothèque standard de C++ propose beaucoup de types et de fonctions génériques.
En particulier, la variété des conteneurs disponibles et la notion d'itérateur qui leur est associée permettent d'exprimer et d'utiliser des algorithmes qui recouvrent la plupart des besoins courants.
Ces fonctionnalités génériques peuvent de plus être très facilement adaptées aux besoins très spécifiques de l'application par des lambda-closures : nous pouvons les considérer comme des fonctions génériques anonymes qui ont la possibilité d'interagir avec leur contexte englobant (comme le corps d'une boucle vis-à-vis de ce qui l'environne).
Comme conséquence de l'introduction de ces procédés systématiques, nous n'avons presque plus jamais besoin d'exprimer explicitement des boucles de parcours avec des compteurs ou des pointeurs : la boucle range-for et les algorithmes de parcours standards, tout en étant fiables et optimisés, conviennent à la grande majorité des besoins.

La réalisation par nos propres moyens de types ou fonctions génériques n'est pas difficile (il suffit de préfixer par la notation template<...>) et est même encouragée afin de limiter les risques de duplication de portions de code source quasi-identiques (sources d'erreurs et difficiles à maintenir).
Que ce soit pour la réalisation de types, de fonctions ou de lambda-closures, l'usage du mot-clef auto est très vivement recommandé puisqu'en évitant d'exprimer des contraintes fortes sur les types il favorise la réutilisation du code source produit.
Le fait que le code générique soit nécessairement défini inline, pour que l'instanciation des templates ait lieu une fois les types effectifs connus, a une conséquence heureuse sur la visibilité du code source par le compilateur, ce qui se traduit par des opportunités d'optimisation.
En particulier, les passages par référence constante n'introduisent pas d'indirection lorsqu'ils sont utilisés sur des types simples.
D'une manière générale, et comme le montre cet outil, ces fonctionnalités génériques n'ajoutent aucun surcoût en temps d'exécution par rapport à un code très spécifique équivalent ; tout le travail est à la charge du compilateur.

Nous n'avons abordé ici que le principe de base de la programmation générique qui suffit pour les besoins courants.
Il est néanmoins possible d'envisager des réalisations bien plus élaborées réservées au programmeurs expérimentés.
Complément : template meta-programming

Code source de l'expérimentation