Spec-Zone.ru › C++

Шаблоны

Шаблон — это сущность 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). Также может определять специализацию шаблона.
имя-концепции
выражение-ограничения
- см. ограничения и концепции

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

(до 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API