230 lines
12 KiB
Markdown
230 lines
12 KiB
Markdown
[temp.class]
|
||
|
||
# 13 Templates [[temp]](./#temp)
|
||
|
||
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.class)
|
||
|
||
### 13.7.2 Class templates [temp.class]
|
||
|
||
#### [13.7.2.1](#general) General [[temp.class.general]](temp.class.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2650)
|
||
|
||
A[*class template*](#def:template,class "13.7.2.1 General [temp.class.general]") defines the layout and operations
|
||
for an unbounded set of related types[.](#general-1.sentence-1)
|
||
|
||
[2](#general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2656)
|
||
|
||
[*Example [1](#general-example-1)*:
|
||
|
||
It is possible for a single class templateList to provide an unbounded set of class definitions:
|
||
one class List<T> for every type T,
|
||
each describing a linked list of elements of type T[.](#general-2.sentence-1)
|
||
|
||
Similarly, a class template Array describing a contiguous,
|
||
dynamic array can be defined like this:template<class T> class Array { T* v; int sz;public:explicit Array(int);
|
||
T& operator[](int);
|
||
T& elem(int i) { return v[i]; }};
|
||
|
||
The prefix template<class T> specifies that a template is being declared and that a[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") T can be used in the declaration[.](#general-2.sentence-3)
|
||
|
||
In other words,Array is a parameterized type withT as its parameter[.](#general-2.sentence-4)
|
||
|
||
â *end example*]
|
||
|
||
[3](#general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2686)
|
||
|
||
[*Note [1](#general-note-1)*:
|
||
|
||
When a member of a class
|
||
template is defined outside of the class template definition,
|
||
the member definition is defined as a template definition with the[*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") equivalent to that
|
||
of the class template[.](#general-3.sentence-1)
|
||
|
||
The names of the template parameters used in the definition of the member
|
||
can differ from the template parameter names used in the class
|
||
template definition[.](#general-3.sentence-2)
|
||
|
||
The class template name in the member definition is followed by
|
||
the template argument list of the [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") ([[temp.arg]](temp.arg "13.4 Template arguments"))[.](#general-3.sentence-3)
|
||
|
||
[*Example [2](#general-example-2)*: template<class T1, class T2> struct A {void f1(); void f2();};
|
||
|
||
template<class T2, class T1> void A<T2,T1>::f1() { } // OKtemplate<class T2, class T1> void A<T1,T2>::f2() { } // error
|
||
|
||
template<class ... Types> struct B {void f3(); void f4();};
|
||
|
||
template<class ... Types> void B<Types ...>::f3() { } // OKtemplate<class ... Types> void B<Types>::f4() { } // error
|
||
|
||
template<typename T> concept C = true;template<typename T> concept D = true;
|
||
|
||
template<C T> struct S {void f(); void g(); void h(); template<D U> struct Inner;};
|
||
|
||
template<C A> void S<A>::f() { } // OK, [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* matchtemplate<typename T> void S<T>::g() { } // error: no matching declaration for S<T>template<typename T> requires C<T> // ill-formed, no diagnostic required: [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* arevoid S<T>::h() { } // functionally equivalent but not equivalenttemplate<C X> template<D Y>struct S<X>::Inner { }; // OK â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[4](#general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2742)
|
||
|
||
In a partial specialization,
|
||
explicit specialization or
|
||
explicit instantiation of a class template,
|
||
the [*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") shall agree in kind with the original class template declaration ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))[.](#general-4.sentence-1)
|
||
|
||
#### [13.7.2.2](#temp.mem.func) Member functions of class templates [[temp.mem.func]](temp.mem.func)
|
||
|
||
[1](#temp.mem.func-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2751)
|
||
|
||
A member function
|
||
of a class template
|
||
may be defined outside of the class
|
||
template definition in which it is declared[.](#temp.mem.func-1.sentence-1)
|
||
|
||
[*Example [1](#temp.mem.func-example-1)*: template<class T> class Array { T* v; int sz;public:explicit Array(int);
|
||
T& operator[](int);
|
||
T& elem(int i) { return v[i]; }};
|
||
|
||
declares three member functions of a class template[.](#temp.mem.func-1.sentence-2)
|
||
|
||
The subscript function can be defined like this:template<class T> T& Array<T>::operator[](int i) {if (i<0 || sz<=i) error("Array: range error"); return v[i];}
|
||
|
||
A constrained member function can be defined out of line:template<typename T> concept C = requires {typename T::type;};
|
||
|
||
template<typename T> struct S {void f() requires C<T>; void g() requires C<T>;};
|
||
|
||
template<typename T>void S<T>::f() requires C<T> { } // OKtemplate<typename T>void S<T>::g() { } // error: no matching function in S<T>
|
||
|
||
â *end example*]
|
||
|
||
[2](#temp.mem.func-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2796)
|
||
|
||
The[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* for a member function of a class template are determined by the[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* of the type of the object for which the member function is called[.](#temp.mem.func-2.sentence-1)
|
||
|
||
[*Example [2](#temp.mem.func-example-2)*:
|
||
|
||
The[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") forArray<T>::operator[] will be determined by theArray to which the subscripting operation is applied[.](#temp.mem.func-2.sentence-2)
|
||
|
||
Array<int> v1(20);
|
||
Array<dcomplex> v2(30);
|
||
|
||
v1[3] = 7; // Array<int>::operator[] v2[3] = dcomplex(7,8); // Array<dcomplex>::operator[] â *end example*]
|
||
|
||
#### [13.7.2.3](#temp.deduct.guide) Deduction guides [[temp.deduct.guide]](temp.deduct.guide)
|
||
|
||
[1](#temp.deduct.guide-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2823)
|
||
|
||
Deduction guides are used
|
||
when a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") or [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") appears as a type specifier
|
||
for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced class template specialization types"))[.](#temp.deduct.guide-1.sentence-1)
|
||
|
||
Deduction guides are not found by name lookup[.](#temp.deduct.guide-1.sentence-2)
|
||
|
||
Instead, when performing class template argument deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9 Class template argument deduction")),
|
||
all reachable deduction guides declared for the class template are considered[.](#temp.deduct.guide-1.sentence-3)
|
||
|
||
[deduction-guide:](#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]")
|
||
[*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]")opt [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) -> [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")opt ;
|
||
|
||
[2](#temp.deduct.guide-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2837)
|
||
|
||
[*Example [1](#temp.deduct.guide-example-1)*: template<class T, class D = int>struct S { T data;};template<class U> S(U) -> S<typename U::type>;
|
||
|
||
struct A {using type = short; operator type();};
|
||
S x{A()}; // x is of type S<short, int> â *end example*]
|
||
|
||
[3](#temp.deduct.guide-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2855)
|
||
|
||
The same restrictions apply
|
||
to the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of a deduction guide
|
||
as in a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||
except that a generic parameter type placeholder ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))
|
||
shall not appear in the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of
|
||
a deduction guide[.](#temp.deduct.guide-3.sentence-1)
|
||
|
||
The [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") shall name a class template specialization[.](#temp.deduct.guide-3.sentence-2)
|
||
|
||
The [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") shall be the same [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#temp.deduct.guide-3.sentence-3)
|
||
|
||
A [*deduction-guide*](#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]") shall inhabit the scope
|
||
to which the corresponding class template belongs
|
||
and, for a member class template, have the same access[.](#temp.deduct.guide-3.sentence-4)
|
||
|
||
Two deduction guide declarations
|
||
for the same class template
|
||
shall not have equivalent [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")*s* if either is reachable from the other[.](#temp.deduct.guide-3.sentence-5)
|
||
|
||
#### [13.7.2.4](#temp.mem.class) Member classes of class templates [[temp.mem.class]](temp.mem.class)
|
||
|
||
[1](#temp.mem.class-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2880)
|
||
|
||
A member class of a class template may be defined outside the class template
|
||
definition in which it is declared[.](#temp.mem.class-1.sentence-1)
|
||
|
||
[*Note [1](#temp.mem.class-note-1)*:
|
||
|
||
The member class must be defined before its first use that requires
|
||
an instantiation ([[temp.inst]](temp.inst "13.9.2 Implicit instantiation"))[.](#temp.mem.class-1.sentence-2)
|
||
|
||
For example,template<class T> struct A {class B;};
|
||
A<int>::B* b1; // OK, requires A to be defined but not A::Btemplate<class T> class A<T>::B { };
|
||
A<int>::B b2; // OK, requires A::B to be defined
|
||
|
||
â *end note*]
|
||
|
||
#### [13.7.2.5](#temp.static) Static data members of class templates [[temp.static]](temp.static)
|
||
|
||
[1](#temp.static-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2899)
|
||
|
||
A definition for a static data member or static data member template may be
|
||
provided in a namespace scope enclosing the definition of the static member's
|
||
class template[.](#temp.static-1.sentence-1)
|
||
|
||
[*Example [1](#temp.static-example-1)*: template<class T> class X {static T s;};template<class T> T X<T>::s = 0;
|
||
|
||
struct limits {template<class T>static const T min; // declaration};
|
||
|
||
template<class T>const T limits::min = { }; // definition â *end example*]
|
||
|
||
[2](#temp.static-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2921)
|
||
|
||
An explicit specialization of a static data member declared as an array of unknown
|
||
bound can have a different bound from its definition, if any[.](#temp.static-2.sentence-1)
|
||
|
||
[*Example [2](#temp.static-example-2)*: template <class T> struct A {static int i[];};template <class T> int A<T>::i[4]; // 4 elementstemplate <> int A<int>::i[] = { 1 }; // OK, 1 element â *end example*]
|
||
|
||
#### [13.7.2.6](#temp.mem.enum) Enumeration members of class templates [[temp.mem.enum]](temp.mem.enum)
|
||
|
||
[1](#temp.mem.enum-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2936)
|
||
|
||
An enumeration member of a class template may be defined outside the class
|
||
template definition[.](#temp.mem.enum-1.sentence-1)
|
||
|
||
[*Example [1](#temp.mem.enum-example-1)*: template<class T> struct A {enum E : T;};template<class T> enum A<T>::E : T { e1, e2 };
|
||
A<int>::E e = A<int>::e1; â *end example*]
|