Files
2025-10-25 03:02:53 +03:00

230 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.1General[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.3Simple 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.1Preamble[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.1Preamble[temp.pre]") ([[temp.arg]](temp.arg "13.4Template 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.1Preamble[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.1Preamble[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.1Preamble[class.pre]") shall agree in kind with the original class template declaration ([[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated 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.3Names 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.3Names 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.3Names 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.3Names of template specializations[temp.names]") or [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9Type 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.8Deduced 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.9Class 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.3Deduction guides[temp.deduct.guide]")
[*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]")opt [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") ) -> [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[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.6Functions[dcl.fct]") of a deduction guide
as in a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
except that a generic parameter type placeholder ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))
shall not appear in the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of
a deduction guide[.](#temp.deduct.guide-3.sentence-1)
The [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names 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.3Names of template specializations[temp.names]") shall be the same [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") as the [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")[.](#temp.deduct.guide-3.sentence-3)
A [*deduction-guide*](#nt:deduction-guide "13.7.2.3Deduction 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.6Functions[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.2Implicit 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*]