Spec-Zone.ru › C++

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

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

Синтаксис

template < список параметров > объявление класса (1)
export template < список параметров > объявление класса (2) (удалено в C++11)

Объяснение

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

Создание экземпляра шаблона класса

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

Явное создание экземпляра

template ключевое слово класса имя шаблона < список аргументов > ; (1)
extern template ключевое слово класса имя шаблона < список аргументов > ; (2) (с C++11)
ключевое слово класса - 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)

См. также

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

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

Spec-Zone.ru

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