Namespaces
Variants

Class template

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Class template
Function template
Miscellaneous

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

Содержание

Синтаксис

template < parameter-list > class-declaration (1)
template < parameter-list > requires constraint class-declaration (2) (начиная с C++20)
export template < parameter-list > class-declaration (3) (удалено в C++11)

Объяснение

class-declaration - объявление класса . Объявленное имя класса становится именем шаблона.
parameter-list - непустой разделенный запятыми список параметров шаблона , каждый из которых является либо параметром-константой , параметром-типом , шаблонным параметром , либо пакетом параметров любого из этих типов.
constraint - ограничивающее выражение , которое ограничивает параметры шаблона, принимаемые данным шаблоном класса
export был необязательным модификатором, который объявлял шаблон как экспортированный (при использовании с шаблоном класса он также объявлял все его члены экспортированными). Файлам, инстанцирующим экспортированные шаблоны, не требовалось включать их определения: было достаточно объявления. Реализации export были редкими и расходились в деталях. (до C++11)

Инстанцирование шаблона класса

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

Явное инстанцирование

template class-key template-name < argument-list > ; (1)
extern template class-key template-name < argument-list > ; (2) (начиная с C++11)
class-key - class , struct или union
1) Явное определение инстанцирования
2) Явное объявление инстанцирования

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

Декларация явной инстанциации (extern template) пропускает этап неявной инстанциации: код, который в противном случае вызвал бы неявную инстанциацию, вместо этого использует явное определение инстанциации, предоставленное в другом месте (что приводит к ошибкам компоновки, если такая инстанциация отсутствует). Это может использоваться для сокращения времени компиляции путем явного объявления инстанциации шаблона во всех, кроме одного, исходных файлах, использующих его, и явного определения в оставшемся файле.

(начиная с C++11)

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

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

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

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

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

Если шаблон функции , шаблон переменной (since C++14) , шаблон функции-члена или функция-член или статический элемент данных шаблона класса явно инстанцируется с определением явного инстанцирования, определение шаблона должно присутствовать в той же единице трансляции.

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

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

Неявная инстанциация

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

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

template<class T>
struct Z // определение шаблона
{
    void f() {}
    void g(); // никогда не определялась
};
template struct 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>
Local classes and any templates used in their members are instantiated as part of the instantiation of the entity within which the local class or enumeration is declared. (since C++17)
Перевод:
Local classes и любые шаблоны, используемые в их членах, инстанцируются как часть инстанцирования сущности, в которой объявлен локальный класс или перечисление. (since C++17)

Ключевые слова

export (до C++11) extern (начиная с C++11)

Смотрите также