Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
PP_laba13.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
71.2 Кб
Скачать

5.1.2 Параметры шаблона, задаваемые по умолчанию

Параметрам класса-шаблона можно присваивать значения по умолчанию, в том числе и для параметров-типов. Для целочисленных параметров допускается за­давать в качестве значения константное выражение, которое компилятор спосо­бен вычислить на этапе трансляции. Для параметров-типов можно указывать либо встроенный тип, либо любое видимое в точке определения шаблона имя тина.

Например, для шаблона «умного» массива Array (листинг 11.1) можно присвоить по умолчанию тип double и ограничить массив десятью элементами. Заголовок шаблона пишется привычным способом

template <typename Т = double, std::size_t N = 10>

В реализации методов ничего изменять не требуется. Тогда допускаются объяв­ления массивов такого вида:

Array <int, 20> t; // полное объявление

Array <date> d; // количество по умолчанию

Аггау <> р; // тип и количество по умолчанию

Пустые угловые скобки указывать обязательно, иначе возникает ошибка време­ни компиляции, поскольку компилятор будет искать обычный класс Array. Во всех объявлениях инициализация выполняется неявно. Класс date должен иметь конструктор без аргументов или конструктор инициализации с аргументом по умолчанию.

Как и для функций с аргументами по умолчанию, присваивать значения нужно правым параметрам. Можно написать заголовок шаблона Array так:

template <typename Т, std::size_t N = 100>

и не разрешается таким способом:

template <typename Т = double, std::size_t N>

Как и для функций с аргументами по умолчанию, при определении объекта нельзя пропускать левые параметры, например:

Array<10> t; // ожидается ошибка трансляции!

Подобное объявление приведет к ошибке трансляции  компилятор не обнару­жит определения шаблона с одним целочисленным параметром.

5.1.3 Специализация шаблона класса

При программировании шаблонов классов часто бывает нужно наряду с общим шаблоном иметь специализированные версии. Для этого в С++ имеется механизм специализации. Специализация заключается в том, что на основе исходного первичного шаблона создается его специализированная версия, в которой на место параметров подставлены аргументы (и по-другому реализованы некоторые методы  в соответствии с аргументами). Специализация  это не присвоение параметров по умолчанию. Шаблон с параметрами по умолчанию является первичным шаблоном, который тоже можно специализировать. Специализация шаблона называется полной, если конкретизированы все аргументы. Если задана только часть аргументов, такая специализация называется частичной.

При определении шаблона и его специализированных версий должен соблюдаться порядок следования: сначала должен быть определен первичный шаблон, и только после него разрешается определять специализированные версии.

tempiate<class Т>

// первичный шаблон

class Class

{ // определения полей и методов класса

};

template < >

// полная специализация

class Class <void *>

{ // определения полей и методов специализированной версии класса

};

Аргументы шаблона, подлежащие специализации, указаны в угловых скобках после имени класса. В данном случае шаблон Class специализирован для бестиповых указателей. Объект такого класса нужно объявлять как объект класса-шаблона с аргументом void *, например:

Class <void *> ddd;

При частичной специализации конкретизируется только часть параметров первичного шаблона. Для указателей возможна частичная специализация, даже если параметр шаблона всего один, например:

template <class Т>

// частичная специализация

class Class<T*>

{ // определения полей и методов специализированной версии класса

};

Обозначение <Т*> после имени подразумевает, что эта специализация должна использоваться всегда, когда аргументом шаблона является указатель любого типа, отличного от void *, для которого «реализована более специализированная полная специализация». Определения объектов выглядят так:

Class <date*> m1; // <T*> - это <date*> -> T = date

Class <int*> m2; // <T*> - это <int*> -> T = int

Class <double**> m3; // <T*> - это <double**> -> T = double*

Чтобы специализировать шаблон, не обязательно иметь полное определение первичного шаблона  достаточно объявления, например:

template <typename T> class Class: // объявление первичного шаблона

template <typename T> class Class <T*> // частичная специализация

{ // определения полей и методов специализированной версии класса

};

template <> class Class <void *> // полная специализация

{ // определения полей и методов специализированной версии класса

};

Все будет корректно работать, если не пытаться инстанцировать первичный шаблон.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]