Порядок разрешения вызова функции




Шаблонная функция может перегружаться при условии, что список формальных параметров каждого ее варианта отличается от остальных либо типами параметров, либо их числом:

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.

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

Приложение В



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-04-27 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: