Лекция 23. Шаблоны (часть 3) презентация

Содержание

Темы Частичная специализация Неполная специализация Шаблонные члены класса Шаблоны как параметры шаблона Функциональные объекты Traits

Слайд 1Лекция 23. Шаблоны (часть 3)
Красс Александр
Alexander.Krass@gmail.com

СПбГУ ИТМО, 2008


Слайд 2Темы
Частичная специализация
Неполная специализация
Шаблонные члены класса
Шаблоны как параметры шаблона
Функциональные объекты
Traits


Слайд 3Частичная специализация
Нам уже знакома полная специализация:
template
class vector { …

};
template<>
class vector { …};
Частичная специализация производится для подтипа:
template
class vector { }; // специализация вектора для указателей.
vector может проходить по своему содержимому и вызывать delete для каждого элемента. STL такой специализации нет.


Слайд 4Частичная специализация (2)
А для чего еще можно выполнять частичную специализацию?


Слайд 5Неполная специализация
Неполная специализация позволяет нам указать часть параметров шаблона.
template

typename Key>
class Map {…};
Вариант Map для случая, когда ключ задается целым:
template
class Map {…};
Неполная специализация не нужна для шаблонных функций, т.к. там можно обойтись перегрузкой.



Слайд 6Шаблонные члены класса
Иногда имеет смысл делать шаблонными не весь класс, а

отдельные методы.
Рассмотрим шаблонный класс Array:
template
class Array { … };
Array это динамический массив в стиле C++.
Когда ему нужно перераспределить память, он вызывает оператор new, а когда удалить, оператор delete.
Очевидно, что для разных случаев нужны разные стратегии управления памятью. (Пояснить?)

Слайд 7Шаблонные члены класса (2)
Вынесем стратегию управления памятью в отдельный класс:
class StdMemoryMgr
{
public:
template


static T* alloc(int n) { return new T[n]; }
template
static void free(T *p) { delete[] p; }
};
Реализуя разные версии этого класса, мы поддерживаем разные стратегии управления памятью. Например, вот так:
class NoFreeMemoryMgr
{
public:
template
static T* alloc(int n) { return new T[n]; }
template
static void free(T *p) {}
};
Класс NoFreeMemoryMgr можно использовать, если удаление очень дорого и оно нам не критично,


Слайд 8Шаблонные члены класса (3)
Теперь наш класс Array будет иметь следующий вид:
template


class Array { … };
Выделение памяти в классе будет производиться так:
T* buf = Allocator::alloc(size);
Освобождение памяти так:
Allocator::free(buf);


Слайд 9Шаблоны как параметры шаблона
Аргументами шаблона могут быть не только простые типы,

но и типы основанные на шаблонах
К примеру, рассмотрим структуру данных стек. У него есть следующие операции:
Push – помещаем элемент в стек
Pop – удаляем элемент из стека
Size – количество элементов в стеке
Стек может быть реализован или на базе списка или на базе массива. Если мы автора класса Stack, мы не можем за пользователя решать, какую структуру нам использовать.
Вынесем структуру в параметр шаблона
template >
class Stack
{
void Push(const Type &v) { impl.push_back (v); }
void Size() const { impl.size(); }

private:
Container impl;
};
Использование:
Stack si1; // стек на базе структуры данных по умолчанию (массива)
Stack > si2; // стек на базе списке. Обратите внимание на пробел между знаками >.

Слайд 10Функциональные объекты
Рассмотрим функцию find1, которая ищет указанное число в массиве типа

int:
const int* find1 ( const int* pool, int n, int x )
{
const int* p = pool;
for ( int i = 0; i {
if ( *p == x ) return p; // success
p++;
}
return 0; // fail
}
Пример использования:
int A[100];
// заполнить A
int* p = find1(A,100,5); // найти 5 в массиве



Слайд 11Функциональные объекты (2)
Обобщим нашу функцию find, добавив возможность поиска элемента по

произвольному условию:
const int* find2 ( const int* pool, int n, bool (*cond)(int) )
{
const int* p = pool;
for ( int i = 0; i {
if ( cond(*p) ) return p; // success
p++;
}
return 0; // fail
}
Пример использования:
int A[100];
bool cond_e5 ( int x ) { return x==5; }
int* p = find2(A,100,cond_e5); // найти элемент массива такой, что cond_e5(A[i]) равен true
Другой пример такого дизайна функция qsort из стандартной библиотеки:
void qsort ( void* base, // first element
size_t num, // number of elements
size_t width, // element size
int (*compare)(const void*, const void*) ); // comparing function



Слайд 12Функциональные объекты (3)
В итоге для реализации обобщенного поведения некоторой функции нам

надо передать в нее callback, который и будет выполнять настройку поведения этой функции
Этот подход имеет и достоинства и недостатки:
Механизм очень гибкий
Низкая скорость из-за лишних вызовов функций. (Функции по указателю нельзя встроить)
Хорошо бы сохранить гибкость callback и увеличить скорость. Воспользуемся помощью классов и шаблонов.

Слайд 13Функциональные объекты (4)
Тип с определенным оператором вызова функции называется функциональным типом.
Функциональные

типы делятся на встроенные и определяемые пользователем
Указатель на функцию – это встроенный тип
Класс с оператором вызова функции – определяемый пользователем

Слайд 14Функциональные объекты (5)
После замены указателей на функциональные объекты и приведения функции

к шаблонному виду получим:
template < typename T, typename Comparator >
T* find3 ( T* pool, int n, Comparator comp )
{
T* p = pool;
for ( int i = 0; i{
if ( comp(*p) ) return p; // success
p++;
}
return 0; // fail
}
Новая версия имеет следующие преимущества:
Ищет в массиве любого типа
Ищет по любому критерию
Она быстрее, чем find2, если оператор вызова функции встраивается.

Слайд 15Функциональные объекты (6)
Теперь мы можем использовать find3 следующим образом:
Определим предикат поиска:
template

typename T, T N>
class less
{
public:
bool operator()(T x) const { return x < N; }
};
2. Используем:
int *p = find3(A, 100, less());
В STL есть аналогичная функция std::find и набор аналогичных предикатов на все случаи жизни.

Слайд 16Traits
Предположим, нам надо написать набор математических функций, работающих с разными типами

данных: float, double, long double, плюс типы, определеяемые пользователем.
При реализации этих функций нам хотелось бы знать о свойствах этих типов:
Максимальное и минимальное значение
Точность
И пр.
Реализация этих функций должна быть максимально обобщенной.
Следовательно, используем шаблоны:

Слайд 17Traits (2)
Все эти величины для стандартных типов определены в файле float.h:
/*

Smallest value such that 1.0+xxx_EPSILON != 1.0 */
#define DBL_EPSILON 2.2204460492503131e-016
#define FLT_EPSILON 1.192092896e-07F
#define LDBL_EPSILON 1.08420217248550443412e-019L
/* max value */
#define DBL_MAX 1.7976931348623158e+308
#define FLT_MAX 3.402823466e+38F
#define LDBL_MAX 1.189731495357231765e+4932L
Но как организовать доступ к этим величинам из наших функций, в зависимости от типа аргументов?
template
bool IsZero(T val)
{ return abs(val) < 10 * eps; } // eps – своя для каждого типа.
Решение заключается в использовании Traits-ов


Слайд 18Traits (3)
Определим обобщенный trait для всех типов:
template
class float_attrs
{ /*

Пусто. Мы ничего не можем сказать про неизвестный тип. */};

template < >
class float_attrs // для double
{
public:
typedef double float_type;
static inline float_type epsilon()
{ return DBL_EPSILON; }
. . .
};

2. Теперь определим специализацию этого класса для различных типов:

template < >
struct float_attrs // для float
{
public:
typedef float float_type;
static inline float_type epsilon()
{ return FLT_EPSILON; }
. . .
};


Слайд 19Traits (4)
Функция IsZero:
template
bool IsZero(T val)
{ return abs(val) < 10

* float_attrs::epsilon(); }
Использование:
IsZero(1.f); // используем float_attrs
float_attrs это и есть трейтс, хранящий атрибуты чисел с плавающей запятой.
Другое применение traits-ов это реализация стратегий, изменяющих поведение объекта.

Слайд 20Спасибо за внимание
Вопросы?


Обратная связь

Если не удалось найти и скачать презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое ThePresentation.ru?

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


Для правообладателей

Яндекс.Метрика