'

Лекция 22. Шаблоны (часть 2)

Понравилась презентация – покажи это...





Слайд 0

Лекция 22. Шаблоны (часть 2) Красс Александр Alexander.Krass@gmail.com СПбГУ ИТМО, 2008


Слайд 1

Темы Неполное инстанцирование Полная специализация Факториал на этапе компиляции typename


Слайд 2

Неполное инстанцирование Рассмотрим шаблонную функцию возведения в степень: template < unsigned N, typename T > T Power ( T v ) { T res = v; for ( int i=1; i<N; i++ ) res *= v; return res; } Функцию Power можно вызвать двумя способами: int r = Power<5, int>(1); int r = Power<5>(1); // Вот это и есть не полное инстанцирование. Компилятор самостоятельно выводит недостающие аргументы шаблона


Слайд 3

Полная специализация Рассмотрим пример функции сравнения двух величин: template < typename T > bool less ( T v1, T v2 ) { return v1 < v2; } Примеры использования: bool l1 = less(1,2); bool l2 = less(1.2,3.4); bool l4 = less(“abcd”,”abcx”); // Будет ли это работать правильно?


Слайд 4

Полная специализация (2) Для последнего примера функция будет выглядеть так: bool less ( char* v1, char * v2 ) { return v1 < v2; // сравнение указателей, а не строк!!! } Итого: Мы хотим иметь обобщенную форму less Версию сравнения строк.


Слайд 5

Полная специализация (3) Можно пойти двумя путями: Перегрузка: bool less(const char *s1, const char *s2) { return strcmp(s1, s2) < 0; } 2. Явная специализация шаблона: template<> bool less<const char*> ( const char* s1, const char* s2 ) { return strcmp(s1,s2)<0; } Теперь наш пример работает правильно Для функций перегрузка и полная явная специализация шаблона эквиваленты. Но для классов понятия перегрузки нет.


Слайд 6

Полная специализация (4) Пример из STL: Обобщенная версия template <typename T> class vector { … }; - динамический массив Специализация template<> class vector<bool> { …}; - массив флагов, каждый флаг это один бит. Реализовано в целях оптимизации по памяти.


Слайд 7

Факториал на этапе компиляции Классический пример из области шаблонов: template < unsigned N > unsigned long Fact ( void ) { if ( N<2 ) return 1; return N*Fact<N-1>(); } Работать не будет!


Слайд 8

unsigned long f5 = Fact<3>(); template<> unsigned long Fact<3> ( void ) { if ( 3<2 ) return 1; return 3*Fact<3-1>(); } template<> unsigned long Fact<2> ( void ) { if ( 2<2 ) return 1; return 2*Fact<2-1>(); } template<> unsigned long Fact<1> ( void ) { if ( 1<2 ) return 1; return 1*Fact<1-1>(); } template<> unsigned long Fact<0> ( void ) { if ( 0<2 ) return 1; return 0*Fact<0-1>(); } Факториал на этапе компиляции (2) Получаем бесконечную рекурсию!


Слайд 9

Факториал на этапе компиляции (3) А вот так работать будет: Обобщенная версия template < unsigned N > unsigned long Fact ( void ) { return N*Fact<N-1>(); } 2. Явная специализация для частных случаев: template<> unsigned long Fact<0> ( void ) { return 1; } template<> unsigned long Fact<1> ( void ) { return 1; }


Слайд 10

unsigned long f5 = Fact<3>(); template<> unsigned long Fact<3> ( void ) { return 3*Fact<3-1>(); } template<> unsigned long Fact<2> ( void ) { return 2*Fact<2-1>(); } template<> unsigned long Fact<1> ( void ) { return 1; } Факториал на этапе компиляции (4) Процесс остановился. Все работает.


Слайд 11

typename Имеем класс: class C { public: typedef int SomeType; }; Определяем шаблонную функцию: template <typename T> void f() { T::SomeType *var; // будет ли это компилироваться? } Компилятор может это распознать или как объявление указателя на тип T::SomeType или как умножение T::SomeType на var. Следовательно, будет ошибка компиляции.


Слайд 12

typename (2) Таким образом при использовании в шаблоне члена класса мы должны явно указывать, что из себя представляет этот член: Если это тип, то перед ним надо указывать typename typename T::SomeType *var; Если это не тип, то typename указывать не нужно.


Слайд 13

Домашнее задание 1 Реализовать вычисление факториала на этапе компиляции с помощью следующей конструкции: template<int N> struct Fact<N> { const static int value = . . . }; 14


Слайд 14

Домашнее задание 2 На основе реализованного на прошлой лекции класса Stack написать решение задачи о Ханойских башнях. Каждый стержень – это экземпляр класса Stack. Параметр шаблона стека T – это класс Disk, имеющий поле diameter. Программа должна уметь выдавать пользователю содержание всех трёх стержней в любой указанный пользователем момент времени (пример: через 50 перекладываний). 15


×

HTML:





Ссылка: