Пространства имён
Варианты
Действия

Шаблон класса

Материал из cppreference.com
< cpp‎ | language
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
Операторы итерации (циклы)
Операторы перехода
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений(до C++17*)
Спецификатор noexcept(C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype(C++11)
auto(C++11)
alignas(C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr(C++11)
Определяемые пользователем(C++11)
Утилиты
Атрибуты(C++11)
Types
Объявление typedef
Объявление псевдонима типа(C++11)
Casts
Неявные преобразования - Явные преобразования
static_cast - dynamic_cast
const_cast - reinterpret_cast
Выделение памяти
Классы
Свойства функции класса
Специальные функции-элементы
Шаблоны
Шаблон класса
Шаблон функции
Разное
 
 

Шаблон класса определяет семейство классов.

Содержание

[править]Синтаксис

template<список-параметров>объявление-класса (1)
exporttemplate<список-параметров>объявление-класса (2) (до C++11)

[править]Объяснение

объявление-классаобъявление класса. Объявленное имя класса становится именем шаблона.
список-параметров непустой список параметров шаблона, разделённых запятыми, каждый из которых является параметром не типом, параметром типом, шаблоном-параметром шаблона, или пакетом параметров из них.
Модификатор explicit был необязательным и объявлял шаблон экспортируемым (при использовании с шаблоном класса он объявлял все его члены также экспортируемыми). В исходных файлы, которые инстанцировали экспортируемые шаблоны, не нужно было включать их определения - было достаточно объявлений. Реализации export были редки и не согласованы в деталях друг с другом. (до C++11)

[править]Создание экземпляра шаблона класса

Шаблон класса сам по себе не является ни типом, ни объектом, ни любой другой сущностью. Из исходного файла, содержащего только определения шаблонов, не генерируется никакого кода. Чтобы компилятор сгенерировал код, данный шаблон должен быть инстанцирован, для чего из шаблона должен быть создан конкретный класс с набором аргументов (или функция для шаблона функции).

[править]Явное создание экземпляра

templateclass|structимя-шаблона<список-аргументов> ; (1)
exporttemplateclass|structимя-шаблона<список-аргументов> ; (2) (начиная с C++11)
1) Явное определение создания экземпляра
2) Явное объявление создания экземпляра

Явное определение создания экземпляра осуществляет непосредственное создания экземпляра класса, структуры или объединения. Такое определение может быть сделано в любом месте программы после определения шаблона, а для заданного списка аргументов, может быть указано только один раз во всей программе.

Явное объявление создания экземпляра (внешний шаблон) пропускает шаг неявного создания экземпляра: код, который иначе бы привёл к неявному созданию экземпляра, вместо этого использует явное определение создания экземпляра, указанное где-либо. Если такого создания экземпляра не было, то возникнут ошибки связывания (link errors). Можно уменьшить время компиляции, явно объявив создания экземпляра шаблона во всех исходных файлах, использующих его, кроме того, где этот шаблон явно определяется.(начиная с C++11)

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

Явное создания экземпляра шаблона может быть указано только в его включающем пространстве имён, если только не используется квалифицированный идентификатор:

namespace N {template<class T>class Y // определение шаблона{void mf(){}};}// template class Y<int>; // ошибка: шаблон класса Y не видим в глобальном пространстве имёнusing N::Y;// template class Y<int>; // ошибка: явное инстанцирование вне пространства имён шаблонаtemplateclass N::Y<char*>;// OK: явное инстанцированиеtemplatevoid N::Y<double>::mf();// OK: явное инстанцирование

Явное создания экземпляра не имеет эффекта, если явная специализация для того же набора аргументов шаблона была уже указана ранее.

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

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

Когда явное создания экземпляра именует специализацию шаблона класса, оно выступает как явное создание экземпляра (объявления или определения) всех его неунаследованных нешаблонных элементов, которые не были ранее явно специализированы в этой единице трансляции. Если этo явное создание экземпляра является определением, оно также является явным объявлением создания экземпляра только для тех элемеетов, которые к этому моменту уже определены.

Явные объявления создания экземпляра игнорируют спецификаторы доступа к элементу класса - типы параметров и возвращаемые типы могут быть приватными.

[править]Неявное создание экземпляра

Когда код ссылается на шаблон в контексте, который требует полностью определённого типа, или когда полнота типа влияет на код, и этoт конкретный тип не был явно инстанцирован, то происходит неявное создание экземпляра. Например, когда создаётся объект этoго типа, но не указатель на этoт тип.

Это применимо и к элементам шаблона класса - если данный элемент не использован в программе, то он не инстанцируется и не требует определения.

template<class T>struct Z // определение шаблона{void f(){}void g();// нет определения};templatestruct Z<double>;// явное инстанцирование Z<double> Z<int> a;// неявное инстанцирование Z<int> Z<char>* p;// здесь ничего не инстанцируется p->f();// здесь происходит неявное инстанцирование Z<char> и Z<char>::f().   // Z<char>::g() нигде не вызывается, поэтому не инстанцируется, а значит определения не требуется

Если шаблон класса был объявлен, но к моменту создания экземпляра не определён, то данное создание экземпляра приводит к ситуации неполноты типа:

template<class T>class X;// объявление, не определение   X<char> ch;// ошибка: X<char> - неполный тип
Локальные классы и любые шаблоны, использованые в их элементах, инстанцируюся как часть создания экземпляра данной сущности, в рамках которой объявлен данный локальный класс или перечисление.(начиная с C++17)

[править]Смотри также

close