Определение_шаблонной_функции

 

Определение шаблона семейства функций начинается со служебного слова template. Для параметризации используется список параметров шаблона, который заключается в обязатель­ные угловые скобки < >. Среди параметров шаблона могут быть типизирующие, не типизирующие и параметры-шаблоны.

 

Каждый типизирующий параметр шаблона обозначается служебным словом typename либо class, за которым следует имя параметра (идентификатор).

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

 

template <typename type>

type abs(type x) {

return x > 0? x: -x;

}

 

Шаблон семейства функций состоит из двух частей – заголовка шаблона

 

template < список_параметров_шаблона >

 

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

В качестве ещё одного примера рассмотрим шаблон семейства функций для обмена значениями двух передаваемых функции аргументов:

 

template <typename Т>

void swap (Т & х, T & у) {

T z = х;

х = у;

у = z;

}

 

Здесь параметр Т шаблона используется не только в заголовке функции для спецификации параметров, но и в теле функции. В заголовке параметр Т определяет тип параметров-ссылок, а в теле шаблонной функции задаёт тип переменной z.

Процесс замены формальных параметров шаблона фактичес­кими при вызове шаблонной функции называется конкретиза ­ цией (инстанцированием) шаблона. Конкретные определения функций, автоматически формируемые на основе шаблона, называются специализациями шаблонной функции. Например, при вызове abs(- 10.3) на основе приведённого шаблона компиля­тор сформирует такое определение (специализацию) функции:

 

double abs(double х) {

return х > 0? х: -х;

}

 

Далее компилятор организует выполнение именно этой функции и в точку вызова в качестве результата вернётся числовое значение 10.3.

Формирование на основе шаблона функций и имеющегося вызова функции конкретного кода функции (создание специали­зации) и называют инстанцированием шаблона.

Компилятор автоматически, анализируя вызовы шаблонных функций в тексте программы, формирует необходимые определе­ния именно для таких типов аргументов, которые использованы в обращениях. Процесс логического (автоматического) определе­ния типов аргументов шаблона функций по типам аргументов в конкретном обращении к шаблонной функции называют выведением (deduction) аргументов шаблона функций.

 

Основные свойства параметров шаблона:

1. Список параметров шаблона функций не может быть пустым.

2. Кроме типизирующих параметров, у шаблона могут быть параметры нетипизирующие. Нетипизирующие параметры явно специфицируются в заголовке шаблона (как обычные параметры функций) и могут иметь тип как базовый, так и производный. Однако на типы нетипизирующих параметров наложены ограничения. Они не могут быть вещественными, не могут быть классами, не могут иметь тип void. Они могут быть:

• целочисленными;

• указателями на объект или функцию;

• ссылками на объект или функцию;

• указателями на поля данных и методы классов.

4. Аргумент, соответствующий нетипизирующему параметру шаблона, должен быть выражением соответствующего параметру типа.

5. В списке параметров шаблона функций может быть несколько типизирующих параметров. Каждый из них должен начинаться со служебного слова class или typename.

6. Аргумент, соответствующий типизирующему параметру шаблона, может быть именем любого типа, как базового, так и производного. Единственное ограничение – для этого типа текст шаблонной функции должен иметь смысл.

7. Недопустимо использовать в заголовке шаблона параметры с одинаковыми именами. Имена параметров должны быть уникальными во всем определении шаблона.

8. Имя типизирующего параметра шаблона имеет в шаб­лонной функции все права имени типа, т.е. с его помощью могут специфицироваться параметры, определяться тип возвращаемого функцией значения и типы любых объектов, локализованных в теле функции. Имя параметра шаблона видно во всем опреде­лении и скрывает другие использования того же идентификатора в области, глобальной по отношению к шаблону. Если внутри тела шаблонной функции необходим доступ к внешним объектам с тем же именем, нужно применять операцию расширения области видимости (::).

 

Типы аргументов шаблона логически выводятся по типам аргументов в вызове функции. Для этой схемы все параметры шаблона должны быть обязательно использованы в спецификациях параметров шаблонной функции. Этим требованиям не соответствует, например, шаблон функции суммирования элементов массива:

 

template <typename T, typename RT>

RT sum(T* begin, T* end) {

T *p;

RT s = RT();

for (p = begin; p!= end; ++p)

s += *p;

return s;

}

 

В данном примере остался не использованным в специ­фикации параметров шаблонной функции параметр шаблона с именем RT. Его применений в качестве типа возвращаемого функцией значения и для определения объекта s в теле функции недостаточно, чтобы компилятор мог по обращению к функции узнать тип аргумента, соответствующего параметру RT. При попытке вызова шаблонной функции, например, так:

 

int mas[] = {1, 2, 3, 4, 5};

cout << sum(mas, mas + 5) << endl;

 

будет выдано сообщение об ошибке:

 

error C2783: 'RT sum(T *,T *)': could not deduce template argument for 'RT'

 

В связи с возможностью подобных затруднений Стандарт определяет общий формат обращения к шаблонным функциям с явным указанием фактических параметров шаблона:

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: