КИТ и Э КБГУ Вторник, 07.05.2024, 07:27
Приветствую Вас Гость | RSS
Меню сайта

Наш опрос
Оцените мой сайт
Всего ответов: 118

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Тема 3.2.Шаблоны функций

  1. Определение шаблона функции
  2. Конкретизация шаблона функции
  3. Явная специализация шаблона функции
  4. Модели компиляции шаблонов

Домашнее задание

 Разработать шаблон функции для обмена значениями максимального и минимального элементов массива.

Элементы массива могут иметь любой тип, для которого определен оператор сравнения на «меньше». Шаблон функции имеет следующий прототип:

template<class T> void swap(T* arr, const int& size);

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

 

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

Функция, которая абстрагируется от типа хотя бы одного из своих параметров, называется обобщённой или родовой функцией. В языке программирования С++ родовые функции определяются шаблонами функций.

Определение шаблона функции имеет следующий вид:

template <список_параметров> определение_функции

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

  • типы;
  • не типы;
  • шаблоны класса.

Объявление параметра-типа имеет следующий вид:

class|typename имя_параметра

где ключевые слова class и typename являются взаимозаменяемыми.

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

Пример 1. В следующем листинге определен шаблон функции min, находящей минимальный элемент массива. При этом тип массива является параметром T шаблона функции.

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;

}

Параметр-не-тип шаблона функции объявляется как переменная, которая используется в определении функции. Эта переменная может иметь один из следующих типов:

  • целочисленный тип;
  • тип перечисления;
  • указатель на объект, функцию или член класса;
  • ссылка на объект или функцию.

Пример 2. В следующем листинге определен шаблон функции min, для нахождения минимального элемента массива, параметр size которого не является типом и определяет размерность массива.

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;

}

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

 

3.2.2. Конкретизация шаблона функции

Процесс создания из шаблона функции определения конкретной функции называется конкретизацией или инстанциированием шаблона. Определения функции, созданные из шаблона функции, называются специализациями шаблона функции или шаблонными функциями. Конкретизация шаблона функции может быть явной или неявной.

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

Шаблон функции конкретизируется неявно, если опущен хотя бы один его параметр. Это может быть как при вызове функции, так и при определении адреса функции. Если какой-то параметр шаблона опущен, то также должны быть опущены и все последующие параметры.

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

#include <iostream>

using namespace std;

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;

}

int main()

{

int a[3] = {3, 1, 2};

double b[3] = {3.1, 1.2, 2.3};

int n = min<int>(a, 3); // явная конкретизация

cout << n << endl; // печатает 1

double m = min(b, 3); // неявная конкретизация

cout << m << endl; // печатает 1.2

return 0;

}

3.2.3. Явная специализация шаблона функции

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

template<> имя_функции<список_аргументов_шаблона>

(параметры_функции) блок_функции

где имя_функции задает имя шаблона функции, а список_аргументов_шаблона содержит аргументы, для которых выполняется явная специализация этого шаблона функции.

Явная специализация шаблона функции используется в двух случаях:

  1. какой-то тип данных не может быть параметром шаблона функции в силу невозможности такой реализации шаблона, которая была бы совместима с другими типами данных;
  2. специальная реализация шаблона функции для какого-то типа данных более эффективна, чем общая реализация шаблона.

Пример 4. Рассмотрим шаблон функции max, которая находит максимальное значение из двух аргументов:

template <class T> T max(T t1, T t2)

{ return t1 > t2 ? t1 : t2; }

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

template <>

char* max<char*>(char* s1, char* s2)

{ return strcmp(s1, s2) > 0 ? s1 : s2; }

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

char* max(char* s1, char* s2)

{ return strcmp(s1, s2) > 0 ? s1 : s2; }

При поиске нужной функции компилятор сначала просматривает нешаблонные функции с точным соответствием типов параметров типам аргументов. Поэтому в этом случае для строк будет вызываться нешаблонная функция max.

3.2.4. Модели компиляции шаблонов

В языке программирования С++ поддерживаются две модели компиляции шаблонов:

  1. модель компиляции с включением,
  2. модель компиляции с разделением.

В модели компиляции с включением определение шаблона должно включаться в каждый файл, в котором этот шаблон конкретизируется. Обычно, в этом случае определение шаблона помещается в заголовочный файл, который затем включается директивой #include в каждый исходный файл, в котором он используется.

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

 

Вход на сайт

Поиск

Календарь
«  Май 2024  »
ПнВтСрЧтПтСбВс
  12345
6789101112
13141516171819
20212223242526
2728293031

Архив записей

Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz

  • Copyright Fatima_Zh © 2024Бесплатный хостинг uCoz