Что такое шаблон (template) в C++?

Ответ

Шаблон (template) в C++ — это механизм метапрограммирования, позволяющий писать обобщённый код, независимый от конкретных типов данных. Компилятор генерирует конкретные реализации (инстанциации) шаблона для тех типов, с которыми он используется.

1. Шаблон функции:

template <typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}
// Использование:
int i = max(10, 20);           // T = int
double d = max(3.14, 2.71);    // T = double
// std::string s = max(std::string("abc"), std::string("def")); // T = std::string

2. Шаблон класса:

template <typename T, size_t N = 100> // Параметр шаблона может быть не только типом
class Stack {
    T elements[N];
    size_t top{0};
public:
    void push(const T& value) { elements[top++] = value; }
    T pop() { return elements[--top]; }
};
// Использование:
Stack<int> intStack;          // Стек для int с размером по умолчанию 100
Stack<double, 500> doubleStack; // Стек для double размером 500

Преимущества:

  • Устранение дублирования кода: Один шаблон заменяет множество функций/классов для разных типов.
  • Безопасность типов: Проверка типов происходит во время компиляции.
  • Производительность: Отсутствие накладных расходов времени выполнения (в отличие от полиморфизма через виртуальные функции).
  • Основа STL: Вся стандартная библиотека (векторы, списки, алгоритмы) построена на шаблонах.

Ответ 18+ 🔞

Слушай, а вот шаблоны в C++ — это вообще ёперный театр, я тебе скажу. Представь, что ты пишешь функцию, которая должна работать с любым типом данных. Без шаблонов пришлось бы для каждого типа писать свою отдельную функцию, и это пиздопроебибна по времени. А тут — раз, и всё обобщил.

1. Шаблон функции — это как универсальный ключ:

template <typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}
// Использование:
int i = max(10, 20);           // T = int
double d = max(3.14, 2.71);    // T = double
// std::string s = max(std::string("abc"), std::string("def")); // T = std::string

Вот смотри: ты написал один раз, а компилятор сам, хитрая жопа, подставит нужный тип. Для интов сгенерит одну версию, для даблов — другую. И не надо руками копипастить код, меняя int на double. Удобно, блядь, до безобразия.

2. Шаблон класса — тут вообще овердохуища возможностей:

template <typename T, size_t N = 100> // Параметр шаблона может быть не только типом, но и числом!
class Stack {
    T elements[N];
    size_t top{0};
public:
    void push(const T& value) { elements[top++] = value; }
    T pop() { return elements[--top]; }
};
// Использование:
Stack<int> intStack;          // Стек для int с размером по умолчанию 100
Stack<double, 500> doubleStack; // Стек для double размером 500

Вот это уже мощь. Ты не только тип данных параметризуешь, но и размер стека можешь задать прямо в угловых скобках. Хочешь стек интов на 100 элементов — пожалуйста. Хочешь стек даблов на 500 — хуй с горы, вот тебе. И всё это проверяется при компиляции, никаких сюрпризов в рантайме.

В чём прикол, спросишь?

  • Код не дублируется: Один шаблон — и на все случаи жизни. Не надо быть мартышкой, которая копирует один и тот же код двадцать раз.
  • Типобезопасно: Компилятор следит, чтобы ты не сунул строку туда, где ожидается число. Если накосячишь — получишь ошибку компиляции, а не падение программы через час работы. Доверия к этому механизму — ебать ноль, потому что он железобетонный.
  • Быстро: Всё инстанцируется на этапе компиляции. Никаких виртуальных функций, никаких накладных расходов. Скорость — пизда рулю.
  • Вся STL на этом стоит: Векторы, списки, алгоритмы — это всё шаблоны, чувак. Без них C++ был бы просто унылым Си с классами.

Короче, шаблоны — это одна из тех фич, из-за которых C++ такой мощный и, одновременно, такой сложный. Но когда вникаешь — понимаешь, что это гениально. Сам от себя охуевал, когда первый раз осознал, как это работает.