Spec-Zone.ru › C++

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

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

Синтаксис

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) Объявление явного инстанцирования

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

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

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

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

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

namespace N
{
    template<class T>
    class Y // template definition
    {
        void mf() {}
    };
}

// template class Y<int>; // error: class template Y not visible in the global namespace
using N::Y;
// template class Y<int>; // error: explicit instantiation outside
                          // of the namespace of the template
template class N::Y<char*>;       // OK: explicit instantiation
template void N::Y<double>::mf(); // OK: explicit instantiation

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

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

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

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

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

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

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

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

template<class T>
struct Z // template definition
{
    void f() {}
    void g(); // never defined
};

template struct Z<double>; // explicit instantiation of Z<double>
Z<int> a;                  // implicit instantiation of Z<int>
Z<char>* p;                // nothing is instantiated here

p->f(); // implicit instantiation of Z<char> and Z<char>::f() occurs here.
        // Z<char>::g() is never needed and never instantiated:
        // it does not have to be defined

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

template<class T>
class X;    // declaration, not definition

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

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

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

См. также

  • Параметры и аргументы шаблона позволяют задавать параметры шаблонов
  • Объявление шаблона функции объявляет шаблон функции
  • Специализация шаблона задаёт определение существующего шаблона для конкретного типа
  • Пакеты параметров позволяют использовать в шаблонах списки типов (начиная с C++11)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/class_template

Spec-Zone.ru

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