17 Templates [temp]

17.5 Template declarations [temp.decls]

17.5.5 Class template partial specializations [temp.class.spec]

primary class template Декларация, в которой имя шаблона класса является идентификатором. Объявление шаблона , в котором имя шаблона класса является simple-template-id это partial specialization шаблон класса с именем в simple-template-id. Частичная специализация шаблона класса обеспечивает альтернативное определение шаблона, которое используется вместо основного определения, когда аргументы в специализации совпадают с аргументами, указанными в частичной специализации ([temp.class.spec.match]). Первичный шаблон должен быть объявлен перед любыми специализациями этого шаблона. Частичная специализация должна быть объявлена ​​перед первым использованием специализации шаблона класса, которая будет использовать частичную специализацию как результат неявной или явной реализации в каждой единице перевода, в которой такое использование происходит; Диагностика не требуется.

Каждая частичная специализация шаблона класса является отдельным шаблоном, и должны быть предоставлены определения для членов частичной специализации шаблона ([temp.class.spec.mfunc]).

[Example:

template<class T1, class T2, int I> class A             { };
template<class T, int I>            class A<T, T*, I>   { };
template<class T1, class T2, int I> class A<T1*, T2, I> { };
template<class T>                   class A<int, T*, 5> { };
template<class T1, class T2, int I> class A<T1, T2*, I> { };

Первое объявление объявляет первичный (неспециализированный) шаблон класса. Второе и последующие объявления объявляют частичную специализацию первичного шаблона. ]end example

Параметры шаблона указываются в прилагаемом списке угловых скобок, который следует сразу за ключевым словом template. Для частичных специализаций список аргументов шаблона явно записывается сразу после имени шаблона класса. Для первичных шаблонов этот список неявно описывается списком параметров шаблона. В частности, порядок аргументов шаблона - это последовательность, в которой они появляются в списке параметров шаблона. [ Example: Список аргументов шаблона для основного шаблона в примере выше <T1, T2, I>. ] [ Список аргументов шаблона не должен указываться в объявлении первичного шаблона. Например,end exampleNote:

template<class T1, class T2, int I>
class A<T1, T2, I> { };                         // error

end note]

Частичная специализация шаблона класса может быть объявлена в любой области , в которой может быть определен соответствующий первичный шаблон ([namespace.memdef],[class.mem],[temp.mem]). [Example:

template<class T> struct A {
  struct C {
    template<class T2> struct B { };
    template<class T2> struct B<T2**> { };      // partial specialization #1
  };
};

// partial specialization of A<T>​::​C​::​B<T2>
template<class T> template<class T2>
  struct A<T>::C::B<T2*> { };                   // #2

A<short>::C::B<int*> absip;                     // uses partial specialization #2

end example]

Сами по себе объявления частичной специализации не могут быть найдены поиском по имени. Скорее, когда используется имя первичного шаблона, также учитываются любые ранее объявленные частичные специализации первичного шаблона. Одним из следствий этого является то, что a, using-declaration который ссылается на шаблон класса, не ограничивает набор частичных специализаций, которые можно найти через using-declaration. [Example:

namespace N {
  template<class T1, class T2> class A { };     // primary template
}

using N::A;                                     // refers to the primary template

namespace N {
  template<class T> class A<T, T*> { };         // partial specialization
}

A<int,int*> a;      // uses the partial specialization, which is found through the using-declaration
                    // which refers to the primary template

end example]

Аргумент, не являющийся типом, считается неспециализированным, если это имя параметра, не являющегося типом. Все остальные аргументы, не относящиеся к типу, являются специализированными.

В списке аргументов частичной специализации шаблона класса действуют следующие ограничения:

  • Тип параметра шаблона, соответствующий специализированному аргументу, не являющемуся типом, не должен зависеть от параметра специализации. [Example:

    template <class T, T t> struct C {};
    template <class T> struct C<T, 1>;              // error
    
    template< int X, int (*array_ptr)[X] > class A {};
    int array[5];
    template< int X > class A<X,&array> { };        // error
    

    end example]

  • Специализация должна отличатьсяmore specialized от основного шаблона.

  • Список параметров шаблона для специализации не должен содержать значений аргументов шаблона по умолчанию.138

  • Аргумент не должен содержать нерасширенный пакет параметров. Если аргумент - этоpack expansion, он должен быть последним аргументом в списке аргументов шаблона.

Их невозможно использовать.

17.5.5.1 Matching of class template partial specializations [temp.class.spec.match]

Когда шаблон класса используется в контексте, который требует создания экземпляра класса, необходимо определить, должно ли создание экземпляра быть сгенерировано с использованием основного шаблона или одной из частичных специализаций. Это делается путем сопоставления аргументов шаблона специализации шаблона класса со списками аргументов шаблона частичных специализаций.

  • Если найдена ровно одна подходящая специализация, экземпляр создается на основе этой специализации.

  • Если найдено более одной подходящей специализации,partial order rules используются для определения, является ли одна из специализаций более специализированной, чем другие. Если ни одна из специализаций не является более специализированной, чем все другие соответствующие специализации, тогда использование шаблона класса неоднозначно и программа плохо сформирована.

  • Если совпадений не найдено, экземпляр создается из основного шаблона.

Частичная специализация соответствует заданному фактическому списку аргументов шаблона, если аргументы шаблона частичной специализации могут быть deduced из фактического списка аргументов шаблона. [Example:

template<class T1, class T2, int I> class A             { };    // #1
template<class T, int I>            class A<T, T*, I>   { };    // #2
template<class T1, class T2, int I> class A<T1*, T2, I> { };    // #3
template<class T>                   class A<int, T*, 5> { };    // #4
template<class T1, class T2, int I> class A<T1, T2*, I> { };    // #5

A<int, int, 1>   a1;            // uses #1
A<int, int*, 1>  a2;            // uses #2, T is int, I is 1
A<int, char*, 5> a3;            // uses #4, T is char
A<int, char*, 1> a4;            // uses #5, T1 is int, T2 is char, I is 1
A<int*, int*, 2> a5;            // ambiguous: matches #3 and #5

end example]

Если аргументы шаблона частичной специализации не могут быть выведены из-за ее структуры template-parameter-list и структуры template-id, программа плохо сформирована. [Example:

template <int I, int J> struct A {};
template <int I> struct A<I+5, I*2> {};     // error

template <int I> struct A<I, I> {};         // OK

template <int I, int J, int K> struct B {};
template <int I> struct B<I, I*2, 2> {};    // OK

end example]

В имени типа, которое относится к специализации шаблона класса, (например, A<int, int, 1>) список аргументов должен соответствовать списку параметров шаблона первичного шаблона. Аргументы шаблона специализации выводятся из аргументов первичного шаблона.

17.5.5.2 Partial ordering of class template specializations [temp.class.order]

Для двух частичных специализаций шаблона класса первая являетсяmore specialized более высокой, чем вторая, если при следующей перезаписи двух шаблонов функций первый шаблон функции более специализирован, чем второй, в соответствии сordering rules for function templates:

  • Каждый из двух шаблонов функций имеет те же параметры шаблона, что и соответствующая частичная специализация.

  • Каждый шаблон функции имеет один параметр функции, тип которого является шаблон класса специализацией , где аргументы шаблона являются соответствующими параметрами шаблона из шаблона функции для каждого аргумента шаблона в template-argument-list из simple-template-id частичной специализации.

[Example:

template<int I, int J, class T> class X { };
template<int I, int J>          class X<I, J, int> { };         // #1
template<int I>                 class X<I, I, int> { };         // #2

template<int I0, int J0> void f(X<I0, J0, int>);                // A
template<int I0>         void f(X<I0, I0, int>);                // B

template <auto v>    class Y { };
template <auto* p>   class Y<p> { };                            // #3
template <auto** pp> class Y<pp> { };                           // #4

template <auto* p0>   void g(Y<p0>);                            // C
template <auto** pp0> void g(Y<pp0>);                           // D

Согласно правилам упорядочивания шаблонов функций, шаблон функции B более специализирован, чем шаблон A функции, а шаблон функции D более специализирован, чем шаблон функции C. Следовательно, частичная специализация №2 более специализирована, чем частичная специализация №1, а частичная специализация №4 более специализирована, чем частичная специализация №3. ]end example

17.5.5.3 Members of class template specializations [temp.class.spec.mfunc]

Список параметров шаблона члена частичной специализации шаблона класса должен соответствовать списку параметров шаблона частичной специализации шаблона класса. Список аргументов шаблона члена частичной специализации шаблона класса должен соответствовать списку аргументов шаблона частичной специализации шаблона класса. Специализация шаблона класса - это отдельный шаблон. Члены частичной специализации шаблона класса не связаны с членами первичного шаблона. Должны быть определены элементы частичной специализации шаблона класса, которые используются способом, требующим определения; определения членов первичного шаблона никогда не используются в качестве определений для членов частичной специализации шаблона класса. Явная специализация члена частичной специализации шаблона класса объявляется так же, как явная специализация первичного шаблона. [Example:

// primary class template
template<class T, int I> struct A {
  void f();
};

// member of primary class template
template<class T, int I> void A<T,I>::f() { }

// class template partial specialization
template<class T> struct A<T,2> {
  void f();
  void g();
  void h();
};

// member of class template partial specialization
template<class T> void A<T,2>::g() { }

// explicit specialization
template<> void A<char,2>::h() { }

int main() {
  A<char,0> a0;
  A<char,2> a2;
  a0.f();           // OK, uses definition of primary template's member
  a2.g();           // OK, uses definition of partial specialization's member
  a2.h();           // OK, uses definition of explicit specialization's member
  a2.f();           // ill-formed, no definition of f for A<T,2>; the primary template is not used here
}

end example]

Если шаблон элемента шаблона класса является частично специализированным, частичные специализации шаблона элемента являются шаблонами элементов включающего шаблона класса; если создается экземпляр шаблона включающего класса ([temp.inst],[temp.explicit]), объявление для каждой частичной специализации шаблона элемента также создается как часть создания членов специализации шаблона класса. Если первичный шаблон члена явно специализирован для данной (неявной) специализации шаблона включающего класса, частичные специализации шаблона члена игнорируются для этой специализации шаблона включающего класса. Если частичная специализация шаблона члена явно специализирована для данной (неявной) специализации шаблона включающего класса, основной шаблон члена и другие его частичные специализации по-прежнему рассматриваются для этой специализации шаблона включающего класса. [Example:

template<class T> struct A {
  template<class T2> struct B {};                     // #1
  template<class T2> struct B<T2*> {};                // #2
};

template<> template<class T2> struct A<short>::B {};  // #3

A<char>::B<int*>  abcip;  // uses #2
A<short>::B<int*> absip;  // uses #3
A<char>::B<int>  abci;    // uses #1

end example]