|
Программирование >> Разработка устойчивых систем
На самом деле контейнер 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:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |