Спецификации шаблонов

Объявление template определяет набор параметризованных классов или функций.

template < template-parameter-list > declaration

Заметки

Список-параметров-шаблона представляет собой список параметров шаблона, которые разделены запятыми. Они могут представлять собой типы (в форме class идентификатор, typename идентификатор или template < список-параметров-шаблона > class идентификатор) или параметры, не являющиеся типами, и будут использоваться в теле шаблона. В параметре шаблона используется один из приведенных ниже вариантов синтаксиса.

parameter-declaration
class identifier [ = typename ] 
typename identifier [ = typename ]
template < template-parameter-list > class [identifier][= name]

Экземпляры шаблона класса создаются примерно так же, как и экземпляры обычных классов, однако в данном случае необходимо включить аргументы шаблона, окруженные угловыми скобками (<>). Эти аргументы шаблона могут иметь любой тип, если в списке аргументов шаблона содержится ключевое слово class или typename, либо значение соответствующего типа, если аргумент не является типом. Для вызова шаблона функции не требуется особый синтаксис, хотя, если параметры шаблона не могут быть выведены из аргументов функции, то могут потребоваться угловые скобки и аргументы шаблона.

Список-параметров-шаблона представляет собой список параметров, используемых шаблоном функции, которые определяют, какие компоненты приведенного ниже кода будут варьироваться. Например:

template< class T, int i > class MyStack...

В этом случае шаблон может получить тип (class T) и константный параметр (int i). После создания экземпляра этот шаблон будет использовать T и целочисленную константу i. В теле объявления MyStack необходимо ссылаться на идентификатор T.

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

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

В следующем примере показано объявление, определение и создание экземпляра шаблона класса с параметром типа T и параметром шаблона i, не являющегося типом.

// template_specifications1.cpp
template <class T, int i> class TestClass 
{
public:
   char buffer[i];
   T testFunc(T* p1 );
};

template <class T, int i>
T TestClass<T,i>::testFunc(T* p1) 
{
    return *(p1++)
};

// To create an instance of TestClass
TestClass<char, 5> ClassInst;
int main()
{
}

Аргументы шаблона, не являющиеся типом

Параметры шаблона, не являющиеся типом, должны иметь целочисленный тип или тип перечисления, указателя, ссылки или указателя на член, а во время компиляции должны быть константами. Они определяются с квалификатором const или volatile. В параметрах шаблона не допускается использование значений с плавающей запятой. В параметрах шаблона не допускается использование объектов типа класс, структура или объединение, не являющихся типами, хотя указатели на такие объекты допускаются. Массивы, передаваемые параметров шаблона, не являющихся типом, преобразуются в указатели. Функции, передаваемые в качестве параметров, не являющихся типом, рассматриваются как указатели на функции. В параметрах шаблона не допускается использование строковых литералов.

Использование ключевого слова typename в объявлении шаблона

Ключевое слово typename может использоваться в списке параметров шаблона. Следующие объявления шаблона идентичны.

template< class T1, class T2 > class X...
template< typename T1, typename T2 > class X...

Аргументы по умолчанию для параметров шаблона

Шаблоны класса могут иметь аргументы по умолчанию, задаваемые при помощи знака =, за которым следует значение или тип по умолчанию. Шаблоны функций не могут иметь аргументы по умолчанию. Дополнительные сведения см. в разделе Аргументы по умолчанию для шаблонов классов.

template<typename Type> class allocator {};
template<typename Type, 
   typename Allocator = allocator<Type> > class stack 
{
};
stack<int> MyStack;

Повторное использование параметров шаблона

Параметры шаблона могут повторно использования в списке параметров шаблона. Например, приведенный ниже код допустим:

// template_specifications2.cpp

class Y 
{
};
template<class T, T* pT> class X1 
{
};
template<class T1, class T2 = T1> class X2 
{
};

Y aY;

X1<Y, &aY> x1;
X2<int> x2;

int main()
{
}

Шаблоны в качестве параметров шаблона

Параметры шаблона сами могут быть шаблонами. Эта конструкция означает, что аргумент сам должен быть шаблоном, а не классом, созданным на основе шаблона. В следующем примере имя A параметра шаблона может быть опущено, поскольку он ни в каком случае не может использования.

// template_specifications3.cpp
#include <stdio.h>

template <class T> struct str1
{
   T t;
};

template <template<class A> class T> struct str2
{
    T<int> t;
};

int main()
{
    str2<str1> mystr2;
    mystr2.t.t = 5;
    printf_s("%d\n", mystr2.t.t);
}

Выходные данные

5

Ссылки в качестве параметров шаблона

В Visual Studio .NET 2003 появилась возможность использовать ссылки в качестве параметров шаблона, не являющихся типом. В предыдущих версиях это было недопустимо.

// references__supported_as_nontype_template_parameters.cpp
#include <stdio.h>

extern "C" int printf_s(const char*,...);
template <int & ri> struct S
{
   S()
   {
      printf_s("ri is %d\n", ri);
   }

   ~S()
   {
      printf_s("ri is %d\n", ri);
   }
};

int i = 1;

int main()
{
   S<i> s;
   i = 0;
}

Выходные данные

ri is 1
ri is 0

Вложенные экземпляры шаблона

До версии Visual Studio 2005 действовало требование о том, что, когда объявляются вложенные экземпляры шаблонов, между списками параметров шаблонов должны быть вставлены пробелы. Следующий синтаксис не допускается.

// template_specifications4.cpp 

template <typename T> 
class A
{
};

template <int n> 
class B 
{
};

int main() 
{
   A<B<22>>();
}

См. также

Ссылки

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

Другие ресурсы

Шаблоны