Вступление
Шаблонные функции и классы служат аналогичной цели в C ++, так как дженерики служат в C #. Они позволяют вам повторно использовать ваш код без написания функции или класса для каждого варианта, который вы хотите. Пока типы, которые вы предоставляете шаблону, имеют связанные с ними функциональные возможности, которые использует шаблон, все в порядке. Если нет, то компилятор выдаст ошибку. Это потому, что компилятор генерирует уникальный класс для каждой используемой вами специализации. Поскольку компилятор создает классы и функции из шаблонов вашей программы, шаблонные функции и классы должны быть помещены в заголовочные файлы и определены полностью встроенными. Таким образом, компилятор может анализировать их для всех файлов исходного кода, которые их используют.
В конечном итоге шаблоны могут стать очень сложными. Стандартная библиотека C ++ демонстрирует мощь и сложность расширенных шаблонов. Несмотря на это, вам не нужны глубокие знания шаблонов для их эффективного использования. Понимание основ шаблонов C ++ поможет вам раскрыть значительный объем функциональности и мощности.
Функции шаблона
Функция шаблона — это отдельная функция, которая принимает как минимум один аргумент шаблона. Тот факт, что он принимает аргумент, делает его неполным до тех пор, пока он не будет вызван с конкретным аргументом, в результате чего шаблон становится полностью определенной функцией. Вот шаблонная функция, которая принимает два аргумента.
Образец: TemplatesSample \ PeekLastItem.h
| 1 2 3 4 5 6 7 | #pragma once template<class T, class U> U PeekLastItem(T& collection) {     return *collection.rbegin(); } | 
 Создание любого шаблона — функции или класса — начинается с ключевого слова template, за которым следуют параметры в квадратных скобках, как показано в предыдущем примере с классом T и классом U. Использование слова class перед T и U не означает аргументы должны быть классами.  Вместо этого думайте о классе как об общем слове, предназначенном для передачи значения неспецифического типа.  У вас может быть шаблон с конкретными типами или со смесью неспецифических типов классов и конкретных типов, таких как template<class T, int> .  Использование T в качестве имени для первого аргумента и U для второго — обычная практика, а не требование.  Вы можете использовать почти что угодно в качестве имени аргумента шаблона. 
  Предыдущая функция принимает ссылку на элемент типа T. Предполагается, что T будет иметь функцию-член с именем rbegin , которая может быть вызвана без аргументов, и будет возвращать тип указателя, который при rbegin ссылки станет объектом типа U. Эта конкретная функция предназначена в первую очередь для работы со многими классами коллекций стандартной библиотеки C ++, хотя любой класс, который соответствует предположениям, которые делает функция в отношении типа T, может использоваться с этой функцией шаблона.  Эта способность принимать любой тип, добавлять к нему необходимые функциональные возможности и, таким образом, делать его пригодным для использования с шаблоном, является основным преимуществом шаблонов. 
Шаблоны классов
Шаблонные классы похожи на шаблонные функции, только они являются классами, а не простыми автономными функциями. Давайте посмотрим на пример.
Образец: TemplatesSample \ SimpleMath.h
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #pragma once template<class T> class SimpleMath { public:     SimpleMath(void) { }     ~SimpleMath(void) { }     T Add(T a, T b)     {         return a + b;     }     T Subtract(T a, T b)     {         return a — b;     }     T Multiply(T a, T b)     {         return a * b;     }     T Divide(T a, T b)     {         return a / b;     } }; | 
Как следует из названия, этот класс не предназначен для демонстрации. Существует только один тип аргумента. Глядя на определение класса, мы можем сделать вывод, что требования для T в этом случае состоят в том, что он имеет следующие операторы, каждый из которых работает с двумя экземплярами T и возвращает экземпляр T:
- +
- —
- *
- /
Хотя они логически связаны с числами, вы можете определить эти операторы для любого класса или типа данных, а затем создать экземпляр этого класса-шаблона, который специализирован для вашего пользовательского класса (например, класса Matrix).
  И последнее замечание: если бы вы определяли функции-члены вне определения класса, но все же находились в том же заголовочном файле, конечно, вам нужно было бы использовать ключевое слово inline в объявлениях;  определения будут выглядеть так: SimpleMath::SimpleMath(void) { } . 
Это последний файл этого примера, показывающий простое использование каждого из предыдущих шаблонов.
Образец: TemplatesSample \ TemplatesSample.cpp
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include <iostream> #include <ostream> #include <vector> #include «SimpleMath.h» #include «PeekLastItem.h» #include «../pchar.h» using namespace std; int _pmain(int /*argc*/, _pchar* /*argv*/[]) {     SimpleMath<float> smf;     wcout << «1.1F + 2.02F = » << smf.Add(1.1F, 2.02F) << «F.»         endl;     vector<const wchar_t*> strs;     strs.push_back(L»Hello»);     strs.push_back(L»World»);     wcout << L»Last word was ‘» <<         PeekLastItem<std::vector<const wchar_t*>,const wchar_t*>(strs) <<         L»‘.»     return 0; } | 
Вывод
Функции шаблонов помогают вам повторно использовать код, что, в свою очередь, делает вашу базу кода более легкой в управлении и СУХОЙ (не повторяйте себя). Лямбда-выражения являются предметом следующей статьи этой серии.
Этот урок представляет собой главу из C ++ Succinctly , бесплатной книги от команды Syncfusion .