Menu
Coddy logo textTech

Templates de fonctions

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 64 sur 104.

Imaginez écrire une fonction pour trouver le maximum de deux entiers, puis réaliser que vous avez besoin de la même logique pour les nombres à virgule flottante, et encore une fois pour les chaînes de caractères. Sans les modèles, vous écririez des fonctions presque identiques pour chaque type. Les modèles de fonction résolvent ce problème en vous permettant d’écrire la logique une seule fois et de laisser le compilateur générer automatiquement des versions spécifiques à chaque type.

Un modèle de fonction utilise le mot-clé template suivi de paramètres de modèle entre chevrons :

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

int main() {
    std::cout << maximum(5, 3) << std::endl;       // Utilise la version int
    std::cout << maximum(3.14, 2.71) << std::endl; // Utilise la version double
    std::cout << maximum('a', 'z') << std::endl;   // Utilise la version char
}

Le compilateur examine chaque appel et génère une fonction concrète pour ce type spécifique. Ce processus est appelé instanciation de modèle. Vous pouvez également spécifier explicitement le type lorsque cela est nécessaire :

std::cout << maximum<double>(5, 3.14) << std::endl;  // Force la version double

Les modèles peuvent avoir plusieurs paramètres de type, ce qui permet des conceptions encore plus flexibles :

template <typename T, typename U>
void printPair(T first, U second) {
    std::cout << first << ", " << second << std::endl;
}

printPair(42, "hello");    // T=int, U=const char*
printPair(3.14, 100);      // T=double, U=int

Les modèles de fonctions fournissent un polymorphisme à la compilation : le type est déterminé lors de la compilation du code, et non lors de l’exécution. Cela signifie qu’il n’y a aucune surcharge à l’exécution par rapport aux fonctions virtuelles, ce qui rend les modèles idéaux pour le code générique où les performances sont essentielles.

challenge icon

Défi

Facile

Construisons une boîte à outils utilitaire à l’aide de modèles de fonctions afin de créer des opérations réutilisables qui fonctionnent avec tout type compatible. Vous organiserez vos fonctions génériques dans un fichier d’en-tête et démontrerez leur flexibilité dans votre programme principal.

Vous allez créer deux fichiers :

  • MathUtils.h : définissez une collection de modèles de fonctions qui effectuent des opérations courantes :

    minimum : une fonction modèle qui prend deux valeurs du même type et renvoie la plus petite.

    clamp : une fonction modèle qui prend trois paramètres : une valeur, une limite inférieure et une limite supérieure. Elle renvoie la valeur limitée à l’intérieur de ces bornes (renvoie low si value est inférieure à low, high si value est supérieure à high, sinon renvoie la valeur elle-même).

    swapValues : une fonction modèle qui prend deux références du même type et échange leurs valeurs.

  • main.cpp : lisez six entrées (chacune sur une ligne distincte) :

    1. Premier entier
    2. Deuxième entier
    3. Une valeur double à limiter
    4. Limite inférieure (double)
    5. Limite supérieure (double)
    6. Un caractère

    Démontrez vos modèles en :

    1. trouvant le minimum des deux entiers et en l’affichant : Min of <a> and <b>: <result>
    2. trouvant le minimum des caractères 'm' et de votre caractère d’entrée, puis en l’affichant : Min of m and <char>: <result>
    3. limitant la valeur double et en l’affichant : Clamp <value> to [<low>, <high>]: <result>
    4. limitant le premier entier à l’intervalle [0, 100] et en l’affichant : Clamp <value> to [0, 100]: <result>
    5. échangeant les deux entiers et en l’affichant : After swapValues: <a>, <b>

Par exemple, avec les entrées 25, 10, 3.7, 1.0, 5.0 et z :

Min of 25 and 10: 10
Min of m and z: m
Clamp 3.7 to [1, 5]: 3.7
Clamp 25 to [0, 100]: 25
After swapValues: 10, 25

Remarquez comment chaque fonction modèle fonctionne sans difficulté avec les entiers, les nombres doubles et les caractères : le compilateur génère la version appropriée pour chaque type que vous utilisez. Votre fonction swapValues doit modifier les variables d’origine par l’intermédiaire de références, démontrant ainsi que les modèles fonctionnent avec des paramètres de référence comme les fonctions ordinaires.

Essayez vous-même

#include <iostream>
#include "MathUtils.h"
using namespace std;

int main() {
    // Lire les entrées
    int a, b;
    double value, low, high;
    char ch;
    
    cin >> a;
    cin >> b;
    cin >> value;
    cin >> low;
    cin >> high;
    cin >> ch;
    
    // TODO: Utiliser le template minimum pour trouver le min de deux entiers
    // Afficher : "Min of <a> and <b>: <result>"
    
    // TODO: Utiliser le template minimum pour trouver le min de 'm' et du caractère d'entrée
    // Afficher : "Min of m and <char>: <result>"
    
    // TODO: Utiliser le template clamp sur la valeur double
    // Afficher : "Clamp <value> to [<low>, <high>]: <result>"
    
    // TODO: Utiliser le template clamp sur le premier entier avec l'intervalle [0, 100]
    // Afficher : "Clamp <value> to [0, 100]: <result>"
    
    // TODO: Utiliser le template swapValues sur les deux entiers
    // Print: "After swapValues: <a>, <b>"
    
    return 0;
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C++ en ligne