ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4313
Скачиваний: 28
Г Л А В А
18
Шаблоны функций
18.1. Определение шаблона
функции
Функция, которая абстрагируется от типа хотя бы одного из сво-
их параметров, называется
обобщенной
или
родовой
(generic)
функцией
. В языке программирования С++ родовые функции оп-
ределяются
шаблонами функций
.
Определение шаблона функции имеет следующий вид:
template <список_параметров>
определение_функции
В угловых скобках указан список параметров шаблона функции,
который не может быть пустым. Параметрами шаблона функции
могут быть:
типы;
не типы;
шаблоны класса.
Объявление параметра-типа шаблона имеет следующий вид:
class|typename имя_параметра
Ключевые слова
class
и
typename
являются взаимозаменяемыми.
В качестве аргумента для параметра-типа запрещается использо-
вание:
Часть II. Язык программирования С++
242
локального типа;
типа без связывания (linkage);
анонимного типа.
Параметр-тип представляет собой тип данных в определении
функции.
Например, в листинге 18.1 определен шаблон функции
xchange
,
обменивающей значения переменных. Тип переменных опреде-
ляется параметром
T
шаблона.
Листинг 18.1. Определение шаблона функции
template <class T> inline void xchange(T &a, T &b)
{
T tmp = а;
a = b;
b = tmp;
}
Параметр-тип шаблона можно использовать для задания типа
возвращаемого функцией значения.
Например, в листинге 18.2 определен шаблон функции
min
, нахо-
дящей минимальный элемент массива. При этом тип массива яв-
ляется параметром
T
шаблона.
Листинг 18.2. Параметр шаблона как тип возвращаемого функцией
значения
template <class T> T min(T *a, const int size)
{
T m = a[0];
for (int i = 1; i < size; ++i)
if (a[i] < m)
m = a[i];
return m;
}
Параметр-не-тип (non-type template parameter) шаблона функции
объявляется как переменная, которая используется в определе-
Глава 18. Шаблоны функций
243
нии функции. Эта переменная может иметь один из следующих
типов:
целочисленный тип;
тип перечисления;
указатель на объект, функцию или член класса;
ссылка на объект или функцию.
Параметр-не-тип может быть определен с квалификаторами
const
и
volatile
.
Например, в листинге 18.3 определен шаблон функции
min
для
нахождения минимального элемента массива, параметр
size
ко-
торого не является типом и определяет размерность массива.
Листинг 18.3. Определение шаблона функции с параметром,
который не является типом
template <int size, class T> T min(T *a)
{
const int n = size;
T m = a[0];
for (int i = 1; i < n; ++i)
if (a[i] < m)
m = a[i];
return m;
}
Параметром шаблона функции может быть также шаблон класса.
Использование шаблонов класса в качестве параметров шаблонов
функций рассмотрено в
разд. 19.10
.
18.2. Конкретизация шаблона
функции
Процесс создания из шаблона функции определения конкретной
функции называется
конкретизацией
или
инстанциированием
(instantiation) шаблона. Определения функции, созданные из шаб-
лона функции, называются
специализациями шаблона функции
Часть II. Язык программирования С++
244
или
шаблонными функциями
. Конкретизация шаблона функции
может быть явной или неявной.
При явной конкретизации шаблона функции после имени функ-
ции нужно сначала указать параметры шаблона в угловых скоб-
ках, а затем — параметры функции в круглых скобках.
Например, следующий вызов функции
xchange
инициирует явную
конкретизацию этой функции:
int n = 10, m = 20;
xchange<int>(n, m);
В этом случае компилятор создаст из шаблона функции опреде-
ление следующей функции:
inline void xchange<int>(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
Отметим, что после имени шаблонной функции в угловых скоб-
ках указаны аргументы шаблона функции, что позволяет компи-
лятору отличать шаблонные функции от обычных нешаблонных
функций.
Шаблон функции конкретизируется неявно, если опущен хотя бы
один его параметр. Это может быть как при вызове функции, так
и при определении адреса функции. Если какой-то параметр
шаблона опущен, то также должны быть опущены и все после-
дующие параметры.
Например, следующий вызов функции
xchange
инициирует неяв-
ную конкретизацию шаблона этой функции:
double a = 1.5, b = 2.5;
xchange(a, b);
В листинге 18.4 приведены примеры явной и неявной конкрети-
зации шаблона функции
xchange
. Предполагается, что определе-
Глава 18. Шаблоны функций
245
ние шаблона функции
xchange
хранится в заголовочном файле
xchange.h, текст которого был приведен в листинге 18.1.
Листинг 18.4. Конкретизация шаблона функции
#include "xchange.h"
#include <iostream>
using namespace std;
int main()
{
int n = 10, m = 20;
xchange<int>(n, m); // явная конкретизация шаблона функции
cout << n << ' ' << m << endl; // печатает 20 10
double a = 1.5, b = 2.5;
xchange(a, b); // неявная конкретизация функции
cout << a << ' ' << b << endl; // печатает 2.5 1.5
return 0;
}
Когда компилятор встречает обращение к функции, то адрес
нужной функции ищется в следующей последовательности:
выполняется поиск нешаблонной функции с точным соответ-
ствием параметров;
выполняется поиск шаблонной функции с точным соответст-
вием параметров;
выполняется поиск нешаблонной функции, которая может
быть приведена к нужной функции, используя преобразования
типов аргументов.
Отсюда видно, что преобразования типов аргументов шаблона
при неявной конкретизации шаблона не используются. Однако
при явной конкретизации шаблона производный класс может
быть приведен к базовому классу.
В листинге 18.5 приведен пример явной конкретизации шаблона
функции с приведением производного класса к базовому классу.
Предполагается, что определение шаблона функции
xchange
хра-
нится в заголовочном файле xchange.h, текст которого был при-
веден в листинге 18.1.