Menu
Coddy logo textTech

Szablony funkcji

Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 64 z 104.

Wyobraź sobie, że piszesz funkcję znajdującą maksimum z dwóch liczb całkowitych, a potem zdajesz sobie sprawę, że potrzebujesz tej samej logiki dla liczb zmiennoprzecinkowych typu double, a następnie także dla ciągów znaków. Bez szablonów musiałbyś napisać niemal identyczne funkcje dla każdego typu. Szablony funkcji rozwiązują ten problem, pozwalając napisać logikę raz i umożliwiając kompilatorowi automatyczne generowanie wersji dla konkretnych typów.

Szablon funkcji używa słowa kluczowego template, po którym następują parametry szablonu ujęte w nawiasy ostrokątne:

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

int main() {
    std::cout << maximum(5, 3) << std::endl;       // Używa wersji dla int
    std::cout << maximum(3.14, 2.71) << std::endl; // Używa wersji dla double
    std::cout << maximum('a', 'z') << std::endl;   // Używa wersji dla char
}

Kompilator analizuje każde wywołanie i generuje konkretną funkcję dla danego typu. Ten proces nazywa się instancjonowaniem szablonu. W razie potrzeby możesz też jawnie określić typ:

std::cout << maximum<double>(5, 3.14) << std::endl;  // Wymusza wersję double

Szablony mogą mieć wiele parametrów typów, co umożliwia tworzenie jeszcze bardziej elastycznych projektów:

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

Szablony funkcji zapewniają polimorfizm czasu kompilacji — typ jest określany podczas kompilowania kodu, a nie w czasie wykonywania. Oznacza to brak narzutu w czasie wykonywania w porównaniu z funkcjami wirtualnymi, dzięki czemu szablony doskonale nadają się do generycznego kodu, w którym wydajność ma kluczowe znaczenie.

challenge icon

Wyzwanie

Łatwy

Stwórzmy zestaw narzędzi, używając szablonów funkcji do tworzenia wielokrotnego użytku operacji, które działają z dowolnym zgodnym typem. Umieścisz swoje funkcje generyczne w pliku nagłówkowym i pokażesz ich elastyczność w programie głównym.

Utworzysz dwa pliki:

  • MathUtils.h: Zdefiniuj zbiór szablonów funkcji wykonujących typowe operacje:

    minimum: funkcja szablonowa, która przyjmuje dwie wartości tego samego typu i zwraca mniejszą z nich.

    clamp: funkcja szablonowa, która przyjmuje trzy parametry: wartość, dolną granicę i górną granicę. Zwraca wartość ograniczoną do tych granic (zwraca low, jeśli value jest mniejsze od low, high, jeśli value jest większe od high, a w przeciwnym razie zwraca samą wartość).

    swapValues: funkcja szablonowa, która przyjmuje dwie referencje tego samego typu i zamienia ich wartości.

  • main.cpp: Wczytaj sześć danych wejściowych (każdą w osobnym wierszu):

    1. Pierwsza liczba całkowita
    2. Druga liczba całkowita
    3. Wartość typu double do ograniczenia
    4. Dolna granica (double)
    5. Górna granica (double)
    6. Znak

    Zademonstruj działanie szablonów, wykonując następujące czynności:

    1. Znajdź minimum z dwóch liczb całkowitych i wyświetl: Min of <a> and <b>: <result>
    2. Znajdź minimum ze znaków 'm' i wczytanego znaku, wyświetlając: Min of m and <char>: <result>
    3. Ogranicz wartość typu double i wyświetl: Clamp <value> to [<low>, <high>]: <result>
    4. Ogranicz pierwszą liczbę całkowitą do zakresu [0, 100] i wyświetl: Clamp <value> to [0, 100]: <result>
    5. Zamień dwie liczby całkowite i wyświetl: After swapValues: <a>, <b>

Na przykład dla danych wejściowych 25, 10, 3.7, 1.0, 5.0 i 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

Zwróć uwagę, jak każdy szablon funkcji działa bezproblemowo z liczbami całkowitymi, wartościami typu double i znakami: kompilator generuje odpowiednią wersję dla każdego używanego typu. Funkcja swapValues powinna modyfikować oryginalne zmienne za pośrednictwem referencji, pokazując, że szablony działają z parametrami będącymi referencjami tak samo jak zwykłe funkcje.

Spróbuj swoich sił

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

int main() {
    // Wczytaj dane wejściowe
    int a, b;
    double value, low, high;
    char ch;
    
    cin >> a;
    cin >> b;
    cin >> value;
    cin >> low;
    cin >> high;
    cin >> ch;
    
    // TODO: Użyj szablonu minimum, aby znaleźć mniejszą z dwóch liczb całkowitych
    // Wypisz: "Min of <a> and <b>: <result>"
    
    // TODO: Użyj szablonu minimum, aby znaleźć mniejszą z wartości 'm' i wczytanego znaku
    // Wypisz: "Min of m and <char>: <result>"
    
    // TODO: Użyj szablonu clamp dla wartości typu double
    // Wypisz: "Clamp <value> to [<low>, <high>]: <result>"
    
    // TODO: Użyj szablonu clamp dla pierwszej liczby całkowitej z zakresem [0, 100]
    // Wypisz: "Clamp <value> to [0, 100]: <result>"
    
    // TODO: Użyj szablonu swapValues dla dwóch liczb całkowitych
    // Wypisz: "After swapValues: <a>, <b>"
    
    return 0;
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C++ online