Les templates avec des paramètres par défaut sont un puissant mécanisme de programmation généralisée en C++.
Historique de la question :
La bibliothèque STL a commencé avec des templates. Plus tard, la possibilité de spécifier des valeurs par défaut pour les paramètres tant des fonctions templates que des classes a été introduite pour rendre les templates plus universels et soutenir l'extensibilité du code.
Problème :
Des conflits non évidents peuvent survenir lorsqu'il existe des surcharges de fonctions normales et de templates, ainsi que des ambiguïtés lors des spécialisations. Les paramètres par défaut dans les templates peuvent accroître la flexibilité, mais entraînent souvent des erreurs de compilation confuses.
Solution :
Il est préférable de minimiser le nombre de valeurs par défaut dans les templates, surtout s'il y a un croisement avec les versions non-templates. La priorité lors de l'appel de fonctions préfère une correspondance exacte avec une fonction normale plutôt qu'une template.
Exemple de code :
template<typename T = int> T multiply(T a, T b = T(2)) { return a * b; } int multiply(int a, int b) { return a + b; }
L'appel multiply(5, 4) choisira la fonction int multiply(int, int), tandis que l'appel multiply<>(5) invoquera le template et b prendra la valeur 2.
Caractéristiques clés :
Peut-on déclarer des paramètres par défaut dans une nouvelle définition d'une fonction template ?
Non, une valeur par défaut ne peut être spécifiée qu'à un seul endroit (généralement dans la déclaration), sinon il y aura une erreur de compilation.
Que se passe-t-il en cas d'ambiguïté entre un template et une fonction non-template ? Comment le compilateur choisit-il quoi appeler ?
Le compilateur privilégie toujours la fonction non-template si elle correspond exactement aux arguments. La template ne sera appelée qu'en l'absence d'une correspondance exacte.
Peut-on spécifier des valeurs par défaut pour un paramètre qui n'est pas de type template (par exemple, pour un entier) ?
Oui, par exemple :
template<typename T, int N = 8> class Array { T data[N]; };
Cas négatif
Une fonction template et une fonction non-template sont déclarées avec des paramètres et des valeurs par défaut correspondants. Dans un module, l'appel fonctionne comme prévu, mais dans un autre, une version inattendue de la fonction est choisie.
Avantages :
Inconvénients :
Cas positif
Pour des configurations qui se chevauchent, des noms différents sont déclarés explicitement pour les fonctions templates et non-templates, avec des valeurs par défaut présentes uniquement dans une des versions.
Avantages :
Inconvénients :