Menu
Coddy logo textTech

Funktionstemplates

Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy — Lektion 64 von 104.

Stellen Sie sich vor, Sie schreiben eine Funktion, um das Maximum von zwei Ganzzahlen zu finden, und stellen dann fest, dass Sie dieselbe Logik für Doubles und erneut für Strings benötigen. Ohne Templates müssten Sie fast identische Funktionen für jeden Typ schreiben. Funktionstemplates lösen dies, indem sie es Ihnen ermöglichen, die Logik einmal zu schreiben und den Compiler automatisch typspezifische Versionen generieren zu lassen.

Eine Funktionsvorlage verwendet das Schlüsselwort template, gefolgt von Template-Parametern in spitzen Klammern:

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

int main() {
    std::cout << maximum(5, 3) << std::endl;       // Verwendet die int-Version
    std::cout << maximum(3.14, 2.71) << std::endl; // Verwendet die double-Version
    std::cout << maximum('a', 'z') << std::endl;   // Verwendet die char-Version
}

Der Compiler untersucht jeden Aufruf und generiert eine konkrete Funktion für diesen spezifischen Typ. Dieser Prozess wird als Template-Instanziierung bezeichnet. Sie können den Typ bei Bedarf auch explizit angeben:

std::cout << maximum<double>(5, 3.14) << std::endl;  // Erzwingt die double-Version

Templates können mehrere Typparameter haben, was noch flexiblere Designs ermöglicht:

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

Funktionstemplates bieten Polymorphismus zur Kompilierzeit – der Typ wird bestimmt, wenn der Code kompiliert wird, nicht zur Laufzeit. Dies bedeutet null Laufzeit-Overhead im Vergleich zu virtuellen Funktionen, was Templates ideal für performancekritischen generischen Code macht.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Utility-Toolkit mit Funktions-Templates erstellen, um wiederverwendbare Operationen zu entwickeln, die mit jedem kompatiblen Typ funktionieren. Sie werden Ihre generischen Funktionen in einer Header-Datei organisieren und deren Flexibilität in Ihrem Hauptprogramm demonstrieren.

Sie werden zwei Dateien erstellen:

  • MathUtils.h: Definieren Sie eine Sammlung von Funktions-Templates, die gängige Operationen ausführen:

    minimum — eine Template-Funktion, die zwei Werte desselben Typs entgegennimmt und den kleineren zurückgibt.

    clamp — eine Template-Funktion, die drei Parameter entgegennimmt: einen Wert, eine Untergrenze (low bound) und eine Obergrenze (high bound). Sie gibt den innerhalb der Grenzen eingeschränkten Wert zurück (gibt low zurück, wenn der Wert kleiner als low ist, high, wenn der Wert größer als high ist, andernfalls den Wert selbst).

    swapValues — eine Template-Funktion, die zwei Referenzen desselben Typs entgegennimmt und deren Werte vertauscht.

  • main.cpp: Lesen Sie sechs Eingaben ein (jede in einer separaten Zeile):

    1. Erste Ganzzahl (Integer)
    2. Zweite Ganzzahl (Integer)
    3. Ein Double-Wert zum Eingrenzen (clamp)
    4. Untergrenze (double)
    5. Obergrenze (double)
    6. Ein Zeichen (Character)

    Demonstrieren Sie Ihre Templates durch:

    1. Finden des Minimums der beiden Ganzzahlen und Ausgabe von: Min of <a> and <b>: <result>
    2. Finden des Minimums des Zeichens 'm' und Ihres eingegebenen Zeichens, Ausgabe von: Min of m and <char>: <result>
    3. Eingrenzen (Clamping) des Double-Wertes und Ausgabe von: Clamp <value> to [<low>, <high>]: <result>
    4. Eingrenzen der ersten Ganzzahl auf den Bereich [0, 100] und Ausgabe von: Clamp <value> to [0, 100]: <result>
    5. Vertauschen der beiden Ganzzahlen und Ausgabe von: After swapValues: <a>, <b>

Zum Beispiel mit den Eingaben 25, 10, 3.7, 1.0, 5.0 und 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

Beachten Sie, wie jede Template-Funktion nahtlos mit Integern, Doubles und Zeichen funktioniert — der Compiler generiert die entsprechende Version für jeden Typ, den Sie verwenden. Ihre swapValues-Funktion sollte die ursprünglichen Variablen über Referenzen modifizieren, was zeigt, dass Templates mit Referenzparametern genauso funktionieren wie reguläre Funktionen.

Spickzettel

Funktionstemplates ermöglichen es Ihnen, generische Funktionen zu schreiben, die mit mehreren Typen funktionieren. Verwenden Sie das Schlüsselwort template gefolgt von Template-Parametern:

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

Der Compiler generiert automatisch typspezifische Versionen durch Template-Instanziierung:

maximum(5, 3);        // Generates int version
maximum(3.14, 2.71);  // Generates double version
maximum('a', 'z');    // Generates char version

Sie können den Typ bei Bedarf explizit angeben:

maximum<double>(5, 3.14);  // Forces double version

Templates unterstützen mehrere Typparameter:

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*

Templates funktionieren mit Referenzparametern zum Ändern von Originalwerten:

template <typename T>
void swapValues(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

Funktionstemplates bieten Compile-Zeit-Polymorphismus ohne Laufzeit-Overhead, was sie ideal für performancekritischen generischen Code macht.

Probier es selbst

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

int main() {
    // Eingaben lesen
    int a, b;
    double value, low, high;
    char ch;
    
    cin >> a;
    cin >> b;
    cin >> value;
    cin >> low;
    cin >> high;
    cin >> ch;
    
    // TODO: Verwende das minimum Template, um das Minimum von zwei Integern zu finden
    // Ausgabe: "Min of <a> and <b>: <result>"
    
    // TODO: Verwende das minimum Template, um das Minimum von 'm' und dem eingegebenen Zeichen zu finden
    // Ausgabe: "Min of m and <char>: <result>"
    
    // TODO: Verwende das clamp Template auf den double-Wert
    // Ausgabe: "Clamp <value> to [<low>, <high>]: <result>"
    
    // TODO: Verwende das clamp Template auf den ersten Integer mit dem Bereich [0, 100]
    // Ausgabe: "Clamp <value> to [0, 100]: <result>"
    
    // TODO: Verwende das swapValues Template auf die zwei Integer
    // Ausgabe: "After swapValues: <a>, <b>"
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung