Узелок на память. Создавая шаблонную функцию, вы, по сути, разрешаете компилятору генерировать столько различных версий этой функции, сколько необходимо для обработки различных способов, которые использует программа для ее вызова.
"Вручную" перегруженная версия обобщенной функции называется явной специализацией.
Несмотря на то что обобщенная функция сама перегружается по мере необходимости, это можно делать и явным образом. Формально этот процесс называется явной специализацией. При перегрузке обобщенная функция переопределяется "в пользу" этой конкретной версии. Рассмотрим, например, следующую программу, которая представляет собой переработанную версию первого примера из этой главы.
// Перегрузка шаблонной функции.
#include <iostream>
using namespace std;
template <class X>
void swapargs(X &a, X &b)
{
X temp;
temp = a;
a = b;
b = temp;
cout << "Выполняется шаблонная функция swapargs.\n";
}
// Эта функция переопределяет обобщенную версию функции swapargs() для int-параметров.
void swapargs(int &а, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
cout << "Это int-специализация функции swapargs.\n";
}
int main()
{
int i=10, j =20;
double x=10.1, y=23.3;
char a='x', b='z';
cout << "Исходные значения i, j: " << i << ' '<< j << '\n';
cout << "Исходные значения x, у: " << x << ' '<< у << '\n';
cout << "Исходные значения a, b: " << a << ' '<< b << '\n';
swapargs(i, j); // Вызывается явно перегруженная функция swapargs().
swapargs(x, у); // Вызывается обобщенная функция swapargs().
swapargs(a, b); // Вызывается обобщенная функция swapargs().
cout << "После перестановки i, j: " << i << ' '<< j << '\n';
cout << "После перестановки x, у: " << x << ' '<< у << '\n';
cout << "После перестановки a, b: " << a << ' '<< b << '\n';
return 0;
}
При выполнении эта программа генерирует такие результаты.
Исходные значения i, j: 10 20
Исходные значения х, у: 10.1 23.3
Исходные значения a, b: х z
Это int-специализация функции swapargs.
Выполняется шаблонная функция swapargs.
Выполняется шаблонная функция swapargs.
После перестановки i, j: 20 10
После перестановки х, у: 23.3 10.1
После перестановки а, b: z х
Как отмечено в комментариях, при вызове функции swapargs(i, j) выполняется явно перегруженная версия функции swapargs(), определенная в программе. Компилятор в этом случае не генерирует эту версию обобщенной функции swapargs(), поскольку обобщенная функция переопределяется явно заданным вариантом перегруженной функции.
Для обозначения явной специализации функции можно использовать новый альтернативный синтаксис, содержащий ключевое слово template. Например, если задать специализацию с использованием этого альтернативного синтаксиса, перегруженная версия функции swapargs() из предыдущей программы будет выглядеть так.
// Использование нового синтаксиса задания специализации.
template<>
void swapargs<int> (int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
cout << "Это int-специализация функции swapargs.\n";
}
Как видите, в новом синтаксисе для обозначения специализации используется конструкция template<>. Тип данных, для которых создается эта специализация, указывается в угловых скобках после имени функции. Для задания любого типа обобщенной функции используется один и тот же синтаксис. На данный момент ни один из синтаксических способов задания специализации не имеет никаких преимуществ перед другим, но с точки зрения перспективы развития языка, возможно, все же лучше использовать новый стиль.