Namespaces
Variants

Templates

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
Miscellaneous

Шаблон — это сущность C++, которая определяет одно из следующих:

(since C++11)
(since C++14)
(начиная с C++20)

Шаблоны параметризуются одним или несколькими template parameters , трёх видов: type template parameters, constant template parameters и template template parameters.

Когда предоставляются аргументы шаблона, или, для function и class (since C++17) templates только, выводятся, они подставляются вместо параметров шаблона для получения специализации шаблона, то есть конкретного типа или конкретной lvalue-функции.

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

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

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

Содержание

Синтаксис

template < список-параметров  > условие-requires  (опционально) объявление (1)
export template < список-параметров  > объявление (2) (до C++11)
template < список-параметров  > concept имя-концепта = выражение-ограничения  ; (3) (начиная с C++20)
parameter-list - непустой список, разделённый запятыми, параметров шаблона , каждый из которых является либо постоянным параметром , либо параметром типа , либо шаблонным параметром , либо пакетом параметров любого из вышеперечисленных (начиная с C++11) .
requires-clause - (начиная с C++20) условие requires , которое задаёт ограничения на аргументы шаблона.
declaration - объявление класса (включая struct и union) , класса-члена или типа перечисления-члена , функции или функции-члена , статического элемента данных в области видимости пространства имён , переменной или статического элемента данных в области видимости класса (начиная с C++14) , или псевдонима шаблона (начиная с C++11) . Также может определять специализацию шаблона .
concept-name
constraint-expression
- см. ограничения и концепции

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

(до C++11)

Идентификаторы шаблонов

Идентификатор шаблона имеет один из следующих синтаксисов:

template-name  < template-argument-list  (необязательно) > (1)
operator op  < template-argument-list  (необязательно) > (2)
operator "" identifier < template-argument-list  (необязательно) > (3) (начиная с C++11)
(устарело)
operator user-defined-string-literal < template-argument-list  (необязательно) > (4) (начиная с C++11)
1) Простой идентификатор шаблона .
2) Идентификатор шаблона функции оператора.
3,4) Идентификатор шаблона функции literal operator .
template-name - идентификатор, который называет шаблон
op - перегружаемый оператор
identifier - идентификатор
user-defined-string-literal - "" за которым следует идентификатор


Простой идентификатор шаблона, который обозначает специализацию шаблона класса, обозначает класс.

Идентификатор шаблона, который именует специализацию шаблона псевдонима, именует тип.

Идентификатор шаблона, который именует специализацию шаблона функции, именует функцию.

Если выполняются все следующие условия, идентификатор шаблона является валидным :

  • Количество аргументов не превышает количество параметров или параметр является шаблонным пакетом параметров (начиная с C++11) .
  • Имеется аргумент для каждого невыводимого непакетного (начиная с C++11) параметра, не имеющего аргумента по умолчанию.
  • Каждый шаблонный аргумент соответствует своему шаблонному параметру.
  • Подстановка каждого шаблонного аргумента в последующие шаблонные параметры (если имеются) выполняется успешно.
  • Если идентификатор шаблона является не зависимым , связанные ограничения удовлетворяются, как указано ниже.
(начиная с C++20)

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

template<class T, T::type n = 0>
class X;
struct S
{
    using type = int;
};
using T1 = X<S, int, int>; // ошибка: слишком много аргументов
using T2 = X<>;            // ошибка: нет аргумента по умолчанию для первого параметра шаблона
using T3 = X<1>;           // ошибка: значение 1 не соответствует типу параметра
using T4 = X<int>;         // ошибка: неудачная подстановка для второго параметра шаблона
using T5 = X<S>;           // OK

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

template<typename T>
concept C1 = sizeof(T) != sizeof(int);
template<C1 T>
struct S1 {};
template<C1 T>
using Ptr = T*;
S1<int>* p;                      // error: constraints not satisfied
Ptr<int> p;                      // error: constraints not satisfied
template<typename T>
struct S2 { Ptr<int> x; };       // error, no diagnostic required
template<typename T>
struct S3 { Ptr<T> x; };         // OK, satisfaction is not required
S3<int> x;                       // error: constraints not satisfied
template<template<C1 T> class X>
struct S4
{
    X<int> x;                    // error, no diagnostic required
};
template<typename T>
concept C2 = sizeof(T) == 1;
template<C2 T> struct S {};
template struct S<char[2]>;      // error: constraints not satisfied
template<> struct S<char[2]> {}; // error: constraints not satisfied
(начиная с C++20)

Если выполняются все следующие условия, два шаблонных идентификатора являются одинаковыми :

  • Их template-name ы или операторы ссылаются на один и тот же шаблон.
  • Их соответствующие аргументы шаблона типа являются одним и тем же типом.
  • Значения параметров шаблона, определяемые их соответствующими константными аргументами шаблона, template-argument-equivalent .
  • Их соответствующие аргументы шаблона шаблона ссылаются на один и тот же шаблон.

Два шаблонных идентификатора, которые совпадают, ссылаются на одну и ту же переменную, (since C++14) класс или функцию.

Шаблонная сущность

Шаблонная сущность (или, в некоторых источниках, "темплоид") — это любая сущность, которая определена (или, для лямбда-выражения , создана) (начиная с C++11) внутри определения шаблона. Все следующие сущности являются шаблонными:

  • класс/функция /переменная (since C++14) шаблон
(since C++20)
  • член шаблонной сущности (например, нешаблонная функция-член шаблона класса)
  • перечислитель перечисления, которое является шаблонной сущностью
  • любая сущность, определённая или созданная внутри шаблонной сущности: локальный класс, локальная переменная, дружественная функция и т.д.
  • тип замыкания лямбда-выражения, которое появляется в объявлении шаблонной сущности
(since C++11)

Например, в

template<typename T>
struct A
{
    void f() {}
};
**Примечание:** Весь код C++ внутри тегов `
` и `` сохранен без изменений, как и требовалось. HTML-разметка и атрибуты также остались нетронутыми.

функция A::f не является шаблоном функции, но всё равно считается шаблонизированной.


Шаблонная функция — это шаблон функции или функция, которая является шаблонной.

Шаблонный класс (templated class) — это шаблон класса или класс, который является шаблонным.

Шаблонная переменная — это шаблон переменной или переменная, которая является шаблонной.

(since C++14)

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

template , export

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
CWG 2293 C++98 правила определения валидности шаблонного
идентификатора не были предоставлены
предоставлены
CWG 2682 C++98
C++14
определения шаблонной функции/шаблонного класса
(C++98)/шаблонной переменной (C++14) отсутствовали
добавлены
P2308R1 C++98 два шаблонных идентификатора различались, если их
соответствующие константные аргументы шаблона
не являются эквивалентными по аргументам шаблона
они различаются, если значения их соответствующих
константных параметров шаблона
не являются эквивалентными по аргументам шаблона

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

Документация C для Generic selection