← Назад к вопросам

Что такое шаблоны (templates)? Чем отличаются от дженериков в других языках?

2.0 Middle🔥 111 комментариев
#ООП и проектирование#Структуры данных и алгоритмы#Язык C++

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Шаблоны (Templates) в C++

Шаблоны позволяют писать обобщённый код, работающий с разными типами. Это compile-time полиморфизм.

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

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

int main() {
    std::cout << max(5, 3) << std::endl;           // 5
    std::cout << max(3.14, 2.71) << std::endl;     // 3.14
    return 0;
}

Компилятор генерирует функцию для каждого типа: max<int>, max<double>.

Шаблоны классов

template<typename T>
class Container {
private:
    T data;
public:
    Container(T val) : data(val) {}
    T get() const { return data; }
};

int main() {
    Container<int> intC(42);
    Container<std::string> strC("hello");
    return 0;
}

Нетиповые параметры

template<int SIZE>
class Array {
private:
    int data[SIZE];
public:
    int getSize() const { return SIZE; }
};

int main() {
    Array<10> arr;
    return 0;
}

Специализация шаблонов

// Частичная специализация для указателей
template<typename T>
class Container {
public:
    void describe() { std::cout << "Generic" << std::endl; }
};

template<typename T>
class Container<T*> {
public:
    void describe() { std::cout << "Pointer" << std::endl; }
};

Шаблоны vs Дженерики

C++ Templates:

  • Инстанциируются на этапе компиляции
  • Полная информация о типе при компиляции
  • Есть частичная специализация
  • Возможно метапрограммирование
  • Code bloat — каждый тип = отдельный код

Java Generics (и другие):

  • Type erasure — информация о типе теряется после компиляции
  • List<Integer> и List<String> становятся одним List
  • Нет частичной специализации
  • Быстрее компилировать
  • Менее гибко

Концепты (C++20)

#include <concepts>

template<typename T>
concept Addable = requires(T a, T b) {
    { a + b } -> std::convertible_to<T>;
};

template<Addable T>
T add(T a, T b) {
    return a + b;
}

Практический пример

template<typename T>
class Stack {
private:
    std::vector<T> items;
public:
    void push(T value) { items.push_back(value); }
    T pop() {
        T top = items.back();
        items.pop_back();
        return top;
    }
    bool isEmpty() const { return items.empty(); }
};

int main() {
    Stack<int> intStack;
    intStack.push(1);
    intStack.push(2);
    std::cout << intStack.pop() << std::endl;  // 2
    return 0;
}

SFINAE (Substitution Failure Is Not An Error)

#include <type_traits>

template<typename T>
enable_if<std::is_integral<T>::value>::type
process(T value) {
    std::cout << "Integer" << std::endl;
}

template<typename T>
enable_if<std::is_floating_point<T>::value>::type
process(T value) {
    std::cout << "Float" << std::endl;
}

Резюме

Шаблоны в C++:

  1. Compile-time полиморфизм через инстанциирование кода
  2. Работают с любыми типами — функции, классы
  3. Более гибкие чем дженерики в Java/C#
  4. Поддерживают специализацию и метапрограммирование
  5. Отличаются от дженериков: нет type erasure
  6. C++20 добавил концепты для ограничения типов