Шаблонная функция может перегружаться при условии, что список формальных параметров каждого ее варианта отличается от остальных либо типами параметров, либо их числом:
template <class T> T f(T,T);
template <class T> T f(T);
template <class T> T f(int, T);
Когда необходимо выбрать один из перегружаемых (overloaded) вариантов функции, функции-шаблоны участвуют в этом процессе, наряду с обычными (нешаблонными) функциями. Обычные функции (с конкретными типами аргументов) называются специализированными. Например,
template <class T> T foo (T x) {…}; //шаблон
int foo (int x) {…}; // специализированный вариант
Специализированная функция всегда имеет более высокий приоритет при разрешении вызова, чем шаблонная. Подробнее правила выбора варианта функции, соответствующего вызову, приведены в Приложении В.
ЗАДАНИЕ 3 (выполнение перегрузки среди шаблонных и обычных функций)
1. Написать программу, в которой определяется шаблон для функции max(x,y), возвращающей большее из переданных ей числовых значений x и y.
2. Написать отдельную специализированную версию функции max(char*,char*), возвращающую "большую" из передаваемых ей символьных строк. Для сравнения использовать библиотечную функцию strcmp (справка по применению функции приведена в Приложении В).
В каждой из функций предусмотреть вывод сообщения о том, что вызвана шаблонная или специализированная функция, и вывод найденного большего.
3. Проверить работу программы на примерах вызовов:
max('a','1'), max(12,17), max("Hello","World").
Объяснить в каждом случае, какое правило использовалось компилятором для осуществления вызова.
Вопросы для контроля
1. Чем статические поля данных отличаются от обычных полей, определяемых в классе?
2. Как объявляются статические поля? Как они определяются (создаются)?
3. Есть ли различия в инициализации public- и private- статических полей?
4. Почему нельзя инициализировать статические поля в конструкторах?
5.Что понимается под шаблоном функции?
6. Что понимается под параметрами настройки шаблона?
7. Как задаются типы данных, используемые для описания шаблона функции?
8. Какие ошибки допущены в следующих объявлениях?
template <class T, class T> T f(T x);
template <class T1, T2> void f(T1 x);
template <class T> T f(int x);
9. Могут ли шаблонные функции участвовать в перегрузке (overload) функций?
10. Какие функции обладают более высоким приоритетом при разрешении вызова — шаблонные или специализированные?
риложение Б). ра конкретного варианта функции для разрешения вызова
Приложение А
Некоторые особенности использования шаблонных функций
1. Параметры настройки шаблона затеняют в описании шаблонной функции одноименные глобальные переменные. Доступ к скрытым таким образом глобальным переменным осуществляется по обычным правилам:
int T;
template <class T> T f(T x) {
T a; // "локальное" T
::T=1; // "глобальное" T
}
2. Функция-шаблон может быть описана как статическая и подставляемая. Спецификаторы inline и static записывают за списком формальных параметров шаблона, но не перед template.
Приложение Б
Преобразования типов фактических аргументов и шаблонные функции
Если формальный тип в шаблоне встречается в списке аргументов шаблона функции несколько раз, то нетривиальные преобразования и расширения типа соответствующих фактических параметров для приведения к одному типу, невозможны.
Тривиальными считаются, например, преобразования при присваивании изменяемому объекту какого-то типа значения неизменяемого (const) объекта того же типа. К тривиальным относят также преобразования между типом массива (неизменяемый указатель) и типом соответствующего указателя.
Однако преобразования int в unsigned int или наоборот уже нетривиальны.
Пример
template <class T> T min (T,T); //прототип
void main(){
unsigned int u=15;
min (u,128);
min (128,u);
}
Оба вызова функции в этом примере приводят к ошибке, так как целые константы имеют (по правилам языка Си) тип int (именно int, а не const int).
Однако в следующем примере преобразование тривиально:
template <class T> T first (T a[]) { return a[0];}
void main() {
int a[]={9,8,7}, *b=a;
cout<< first (b)<<endl; }
хотя имя массива имеет тип const int, а переменная b — тип int.
Важно отметить, что стандартные и сложные преобразования типа не будут выполняться и с аргументами не параметризованных (явно указанных) типов шаблонной функции.
Приложение В