Шаблоны
Шаблон — это сущность C++, которая определяет одно из следующего:
- семейство классов (шаблон класса), которое может быть вложенными классами
- семейство функций (шаблон функции), которое может быть член-функциями
| (с C++11) |
| (с C++14) |
| (с C++20) |
Шаблоны параметризуются одним или несколькими параметрами шаблона трёх видов: параметрами шаблона типа, параметрами шаблона нетипа и параметрами шаблона шаблона.
Когда предоставляются аргументы шаблона или, для шаблонов функций и классов(с C++17) только, выведенные, они подставляются вместо параметров шаблона, чтобы получить *специализацию* шаблона, то есть конкретный тип или конкретную функцию lvalue. Специализации также могут быть предоставлены явно: разрешены *полные специализации* для шаблонов классов, переменных(с C++14) и функций, *частичные специализации* разрешены только для шаблонов классов и шаблонов переменных(с C++14).
Когда специализация шаблона класса упоминается в контексте, требующем полного типа объекта, или когда специализация шаблона функции упоминается в контексте, требующем наличия определения функции, шаблон *инстанцируется* (код для него фактически компилируется), если шаблон не был уже явно специализирован или явно инстанцирован. Инстанциация шаблона класса не инстанцирует ни одну из его член-функций, если они также не используются. Во время компоновки одинаковые инстанциации, созданные различными трансляционными единицами, объединяются.
Определение шаблона класса должно быть видно в момент неявной инстанциации, поэтому библиотеки шаблонов обычно предоставляют все определения шаблонов в заголовках (например, большинство библиотек Boost — это библиотеки с заголовками только).
Синтаксис
template <список-параметров > ограничения (необязательно) объявление | (1) | |
export template <список-параметров > объявление | (2) | (до C++11) |
template <список-параметров > concept имя-концепции = выражение-ограничения ; | (3) | (с C++20) |
| список-параметров | - | непустой список параметров шаблона, разделённых запятыми, каждый из которых является параметром нетипа, параметром типа, параметром шаблона или параметром-пакетом любого из них(с C++11). |
| ограничения | - | (с C++20) оператор requires, который определяет ограничения на аргументы шаблона. |
| объявление | - | объявление класса (включая struct и union), вложенного класса или перечислимого типа члена, функции или член-функции, статического члена данных на уровне пространства имён, переменной или статического члена данных на уровне класса(с C++14), или шаблона псевдонима типа(с 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>; // error: too many arguments
using T2 = X<>; // error: no default argument for first template parameter
using T3 = X<1>; // error: value 1 does not match type-parameter
using T4 = X<int>; // error: substitution failure for second template parameter
using T5 = X<S>; // OK| Когда имя шаблона простого идентификатора шаблона называет ограниченный шаблон, не являющийся функцией, или ограниченный параметр шаблона шаблона, но не член-шаблон, являющийся членом неизвестной специализации, и все аргументы шаблона в простом идентификаторе шаблона не зависят от контекста, связанные ограничения ограниченного шаблона должны выполняться: 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) |
Два идентификатора шаблона эквивалентны, если
- их имена шаблонов относятся к одному и тому же шаблону, и
- их соответствующие аргументы шаблона типа являются одинаковыми типами, и
- их соответствующие аргументы шаблона нетипа являются эквивалентными аргументам-шаблонам после преобразования к типу параметра шаблона, и
- их соответствующие аргументы шаблона шаблона относятся к одному и тому же шаблону.
Два одинаковых идентификатора шаблона ссылаются на одну и ту же переменную,(с C++14) класс или функцию.
Сущность шаблона
Шаблонное сущность (или, в некоторых источниках, "темплоид") — это любая сущность, которая определена (или, для выражения лямбда-функции, создана)(с C++11) внутри определения шаблона. Все перечисленное ниже являются шаблонными сущностями:
- шаблон класса/функции/переменной(с C++14)
| (с C++20) |
- член шаблонной сущности (например, нешаблонная функция-член шаблона класса)
- перечислитель перечисления, являющийся шаблонной сущностью
- любая сущность, определённая или созданная внутри шаблонной сущности: локальный класс, локальная переменная, дружественная функция и т. д.
| (с C++11) |
Например, в
template<typename T>
struct A
{
void f() {}
};функция A::f не является шаблоном функции, но всё равно считается шаблонной.
Шаблонная функция — это шаблон функции или функция, которая является шаблонной.
Шаблонный класс — это шаблон класса или класс, который является шаблонным.
| Шаблонная переменная — это шаблон переменной или переменная, которая является шаблонной. | (с C++14) |
Defect reports
Следующие дефекты, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применено к | Поведение, как опубликовано | Правильное поведение |
|---|---|---|---|
| CWG 2293 | C++98 | правила определения, является ли template-id допустимым, не были предоставлены | предоставлены |
| CWG 2682 | C++98 C++14 | определения шаблонной функции/шаблонного класса (C++98)/ шаблонной переменной (C++14) отсутствовали | добавлены |
See also
| Документация C по Общий выбор |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/templates