Программирование >>  Разработка устойчивых систем 

1 ... 60 61 62 [ 63 ] 64 65 66 ... 196


На самом деле контейнер vector<bool> более гибок, но об этом речь пойдет в следующем разделе.

Неполная специализация и приоритеты шаблонов классов

Шаблоны классов могут специализироваться частично. Это означает, что хотя бы один из параметров в специализации остается открытым . Так, vector<bool> определяет тип объекта (bool), но оставляет неопределенным тип распределителя памяти. Рассмотрим фактическое объявление vector<bool>:

tempiate<class Allocator> class vector<bool, Allocator>:

Внешними признаками неполных специализаций являются непустой список параметров в фигурных скобках после ключевого слова template (оставшиеся параметры) и после класса (заданные аргументы). Такое определение vector<bool> позволяет выбрать нестандартный тип распределителя памяти даже при фиксированном типе элементов bool. Другими словами, специализация вообще и неполная специализация в особенности образуют некую разновидность перегрузки шаблонов icTiaccoB.

Правила выбора шаблона для специализации напоминают неполные приоритеты шаблонов функций - выбирается наиболее специализированный шаблон. Строки внутри функций f() в следующем примере поясняют роль каждого определения щаблона:

: C05:PartialOrcler2.cpp

Неполные приоритеты при выборе шаблона класса

linclude <iostream>

using namespace std:

tempiate<class T. class U> class С { public:

void fO { cout Primary Tempiate\n : }

tempiate<class U> class C<int. U> { public:

void f() { cout T == int\n ; }

tempiate<class T> class C<T. double> { public:

void fO { cout U == double\n : }

tempiate<class T. class U> class C<T*. U> { public:

void fO { cout T* used \n : }

tempiate<class T. class U> class C<T. U*> { public:

void f() { cout U* used\n : }

tempiate<class T. class U> class C<T*. U*> {



public:

void fO { cout T* and U* used\n ; }

tempiate<class T> class C<T. T> { public:

void fO { cout T == U\n : }

int mainO {

C<float. int>().f(): 1

C<int. float>().f(): 2

C<float. double>().f(): 3

C<float. float>().f(): 4

C<float*. float>().f(): 5

C<float. float*>().f(): 6

C<float*. int*>().f(): 7

Основной шаблон Т == int и == double Т == и

Используется Т* [float] Используется U* [float] Используются Т* и и* [float.int]

Следующие вызовы неоднозначны:

C<int. int>().f(): C<double. double>().f(): C<float*. float*>().f(): C<int. int*>().f(): C<int*. int*>().f():

} III:-

Как видите, частичная специализация также может производиться по тому, являются ли параметры шаблона указателями, и по их совпадению. При использовании специализации Т*, как в строке 5, Т представляет не передаваемый тип указателя верхнего уровня, а тот тип, на который этот указатель ссылается (в данном случае float). Спецификация Т* может рассматриваться как условное обозначение для поиска типов указателей. Если передать в первом аргументе шаблона int**, то Т будет соответствовать int*. Строка 8 неоднозначна, потому что наличие первого параметра типа int и совпадение двух типов параметров не зависят друг от друга - один аспект не обеспечивает большей специализации по сравнению с другим. Аналогичная логика применима к строкам 9-12.

Пример

На базе шаблона класса легко можно определять производные шаблоны классов. Допустим, если шаблон vector делает большую часть того, что вам нужно, но в вашей конкретной ситуации нужна поддержка автоматической сортировки, вы можете легко воспользоваться готовым кодом vector. В следующем примере создается шаблон, производный от vector<T>, и в него добавляется поддержка сортировки. Учтите, что создание классов, производных от класса vector, который не имеет виртуального деструктора, может оказаться рискованным, если в деструкторе должна выполняться зачистка.

: C05:Sortable.h Специализация шаблона #ifndef SORTABLE H #define SORTABLE H #include <cstring> #include <cstddef> #include <string>



tempiate<cl ass T>

void Sortable<T>::sort() { Простая сортировка for(size t i = this->size(): i > 0; i--) for(size t j - 1: j < i: if(this->at(j-l) > this->at(j)) { T t = this->at(j-l): this->at(j-l) = this->at(j): th1s->at(j) = t:

Неполная специализация для указателей: tempiate<class T>

class Sortable<T*> : public std::vector<T*> { public: void sortO;

tempiate<cl ass T> void Sortable<T*>::sort() { for(size t i = this->size(); i > 0: i--) for(size t j = 1: j < i: if(nhis->at(j-l) > nhis->at(j)) { T* t - this->at(j-l): this->at(j-l) = this->at(j); this->at(j) = t:

Полная специализация для char*

(Объявлена подставляемой для удобства -

обычно тело функции находится в отдельном файле.

а в заголовке остается только объявление)

tempiate<>

inline void Sortable<char*>::sort() { for(size t i = sizeO: i > 0; i--) for(size t j = 1: j < i: ++j) if(std::strcmp(this->at(j-l). this->at(j)) > 0) { char* t = this->at(j-l): this->at(j-l) - this->at(j): this->at(j) = t:

lendif SORTABLE H /:-

Шаблон Sortable устанавливает ограничение для всех классов, для которых он специализируется (кроме одного): класс должен содержать оператор >. Полная специализация сортирует векторы типа char*, сравнивая строки С с нуль-завершителями при помощи функции strcmp(). Наличие уточнения this-> в данном слу-

linclude <vector> using std::size t:

tempiate<cl ass T>

class Sortable : public std::vector<T> { public: void sortO:



1 ... 60 61 62 [ 63 ] 64 65 66 ... 196

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.004
При копировании материалов приветствуются ссылки.
Яндекс.Метрика