Menu
Coddy logo textTech

Шаблоны функций

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 64 из 104.

Представьте, что вы пишете function, чтобы find maximum двух integers, а затем понимаете, что вам нужна та же логика для double и снова для строк. Без шаблонов вам пришлось бы писать почти одинаковые function для каждого типа. Шаблоны function решают эту проблему, позволяя написать логику один раз и автоматически поручить компилятору сгенерировать версии для конкретных типов.

Шаблон функции использует ключевое слово template, за которым следуют параметры шаблона в угловых скобках:

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

int main() {
    std::cout << maximum(5, 3) << std::endl;       // Использует версию int
    std::cout << maximum(3.14, 2.71) << std::endl; // Использует версию double
    std::cout << maximum('a', 'z') << std::endl;   // Использует версию char
}

Компилятор анализирует каждый вызов и создаёт конкретную function для этого типа. Этот процесс называется инстанцированием шаблона. При необходимости вы также можете явно указать тип:

std::cout << maximum<double>(5, 3.14) << std::endl;  // Принудительно использует версию double

Шаблоны могут иметь несколько параметров типа, что позволяет создавать ещё более гибкие конструкции:

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

Шаблоны функций обеспечивают полиморфизм на этапе компиляции — тип определяется при компиляции кода, а не во время выполнения. Это означает отсутствие накладных расходов во время выполнения по сравнению с виртуальными функциями, что делает шаблоны идеальными для обобщённого кода, критичного к производительности.

challenge icon

Задание

Легко

Давайте создадим набор утилит с использованием шаблонов function для создания повторно используемых операций, работающих с любым совместимым типом. Вы организуете свои обобщённые функции в заголовочном файле и продемонстрируете их гибкость в своей программе main.

Вы создадите два файла:

  • MathUtils.h: Define набор шаблонов function, выполняющих распространённые операции:

    minimum: шаблонная function, которая принимает два значения одного и того же типа и возвращает меньшее из них.

    clamp: шаблонная function, которая принимает три параметра: значение, нижнюю границу и верхнюю границу. Она возвращает значение, ограниченное заданными границами (возвращает low, если value меньше low, high, если value больше high, в противном случае возвращает само value).

    swapValues: шаблонная function, которая принимает две ссылки одного и того же типа и exchanges их значения.

  • main.cpp: Read шесть входных значений (каждое в отдельной строке):

    1. Первое integer
    2. Второе integer
    3. Значение double для ограничения
    4. Нижняя граница (double)
    5. Верхняя граница (double)
    6. A character

    Продемонстрируйте свои шаблоны, выполнив следующие действия:

    1. Найдите minimum двух integer и выведите: Min of <a> and <b>: <result>
    2. Найдите minimum characters 'm' и вашего входного character и выведите: Min of m and <char>: <result>
    3. Ограничьте значение double и выведите: Clamp <value> to [<low>, <high>]: <result>
    4. Ограничьте первый integer диапазоном [0, 100] и выведите: Clamp <value> to [0, 100]: <result>
    5. Поменяйте местами два integer и выведите: After swapValues: <a>, <b>

Например, при входных значениях 25, 10, 3.7, 1.0, 5.0 и 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

Обратите внимание, как каждая шаблонная function без проблем работает с integer, double и character: компилятор создаёт подходящую версию для каждого используемого вами типа. Ваша function swapValues должна изменять исходные переменные через ссылки, демонстрируя, что шаблоны работают с параметрами-ссылками так же, как обычные функции.

Попробуйте сами

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

int main() {
    // Считать входные данные
    int a, b;
    double value, low, high;
    char ch;
    
    cin >> a;
    cin >> b;
    cin >> value;
    cin >> low;
    cin >> high;
    cin >> ch;
    
    // TODO: Используйте шаблон minimum, чтобы найти минимум двух целых чисел
    // Вывести: "Min of <a> and <b>: <result>"
    
    // TODO: Используйте шаблон minimum, чтобы найти минимум 'm' и входного символа
    // Вывести: "Min of m and <char>: <result>"
    
    // TODO: Используйте шаблон clamp для значения double
    // Вывести: "Clamp <value> to [<low>, <high>]: <result>"
    
    // TODO: Используйте шаблон clamp для первого целого числа с диапазоном [0, 100]
    // Вывести: "Clamp <value> to [0, 100]: <result>"
    
    // TODO: Используйте шаблон swapValues для двух целых чисел
    // Print: "After swapValues: <a>, <b>"
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C++