Working Draft, Standard for Programming Language C++ (N4713, 2017 year) - page 12

 

  Главная      Manuals     Working Draft, Standard for Programming Language C++ (N4713, 2017 year)

 

Search            copyright infringement  

 

 

 

 

 

 

 

 

 

 

 

Content      ..     10      11      12      13     ..

 

 

 

Working Draft, Standard for Programming Language C++ (N4713, 2017 year) - page 12

 

 

17.4.4
Partial ordering by constraints
[temp.constr.order]
1
A constraint P subsumes a constraint Q if and only if, for every disjunctive clause Pi in the disjunctive
normal form139 of P , Pi subsumes every conjunctive clause Qj in the conjuctive normal form140 of Q, where
(1.1)
a disjunctive clause Pi subsumes a conjunctive clause Qj if and only if there exists an atomic constraint
Pia in Pi for which there exists an atomic constraint Qjb in Qj such that Pia subsumes Qjb, and
(1.2)
an atomic constraint A subsumes another atomic constraint B if and only if the A and B are identical
using the rules described in 17.4.1.2.
[ Example: Let A and B be atomic constraints (17.4.1.2). The constraint A ∧ B subsumes A, but A does not
subsume A ∧ B. The constraint A subsumes A ∨ B, but A ∨ B does not subsume A. Also note that every
constraint subsumes itself.
— end example ]
2
[Note: The subsumption relation defines a partial ordering on constraints. This partial ordering is used to
determine
(2.1)
the best viable candidate of non-template functions (16.3.3),
(2.2)
the address of a non-template function (16.4),
(2.3)
the matching of template template arguments (17.3.3),
(2.4)
the partial ordering of class template specializations (17.6.5.2), and
(2.5)
the partial ordering of function templates (17.6.6.2).
— end note ]
3
A declaration D1 is at least as constrained as a declaration D2 if
(3.1)
D1 and D2 are both constrained declarations and D1’s associated constraints subsume those of D2; or
(3.2)
D2 has no associated constraints.
4
A declaration D1 is more constrained than another declaration D2 when D1 is at least as constrained as D2,
and D2 is not at least as constrained as D1. [ Example:
template<typename T> concept C1 = requires(T t) { --t; };
template<typename T> concept C2 = C1<T> && requires(T t) { *t; };
template<C1 T> void f(T);
// #1
template<C2 T> void f(T);
// #2
template<typename T> void g(T); // #3
template<C1 T> void g(T);
// #4
f(0);
// selects #1
f((int*)0);
// selects #2
g(true);
// selects #3 because C1<bool> is not satisfied
g(0);
// selects #4
— end example ]
17.5
Type equivalence
[temp.type]
1
Two template-ids refer to the same class, function, or variable if
(1.1)
their template-names, operator-function-ids, or literal-operator-ids refer to the same template and
(1.2)
their corresponding type template-arguments are the same type and
(1.3)
their corresponding non-type template arguments of integral or enumeration type have identical values
and
(1.4)
their corresponding non-type template-arguments of pointer type refer to the same object or function
or are both the null pointer value and
139) A constraint is in disjunctive normal form when it is a disjunction of clauses where each clause is a conjunction of atomic
constraints.
[ Example: For atomic constraints A, B, and C, the disjunctive normal form of the constraint A ∧ (B ∨ C) is
(A ∧ B) ∨ (A ∧ C). Its disjunctive clauses are (A ∧ B) and (A ∧ C). — end example ]
140) A constraint is in conjunctive normal form when it is a conjunction of clauses where each clause is a disjunction of atomic
constraints.
[ Example: For atomic constraints A, B, and C, the constraint A ∧ (B ∨ C) is in conjunctive normal form. Its
conjunctive clauses are A and (B ∨ C).
— end example ]
§ 17.5
322
(1.5)
their corresponding non-type template-arguments of pointer-to-member type refer to the same class
member or are both the null member pointer value and
(1.6)
their corresponding non-type template-arguments of reference type refer to the same object or function
and
(1.7)
their corresponding template template-arguments refer to the same template.
[ Example:
template<class E, int size> class buffer { /* ... */ };
buffer<char,2*512> x;
buffer<char,1024> y;
declares x and y to be of the same type, and
template<class T, void(*err_fct)()> class list { /* ... */ };
list<int,&error_handler1> x1;
list<int,&error_handler2> x2;
list<int,&error_handler2> x3;
list<char,&error_handler2> x4;
declares x2 and x3 to be of the same type. Their type differs from the types of x1 and x4.
template<class T> struct X { };
template<class> struct Y { };
template<class T> using Z = Y<T>;
X<Y<int> > y;
X<Z<int> > z;
declares y and z to be of the same type.
— end example ]
2
If an expression e is type-dependent (17.7.2.2), decltype(e) denotes a unique dependent type. Two such
decltype-specifier s refer to the same type only if their expressions are equivalent (17.6.6.1). [ Note: However,
such a type may be aliased, e.g., by a typedef-name.
— end note ]
17.6
Template declarations
[temp.decls]
1
A template-id, that is, the template-name followed by a template-argument-list shall not be specified in the
declaration of a primary template declaration. [ Example:
template<class T1, class T2, int I> class A<T1, T2, I> { };
// error
template<class T1, int I> void sort<T1, I>(T1 data[I]);
// error
— end example ] [Note: However, this syntax is allowed in class template partial specializations (17.6.5).
— end note ]
2
For purposes of name lookup and instantiation, default arguments, partial-concept-ids, requires-clauses (Clause
17), and noexcept-specifier s of function templates and of member functions of class templates are considered
definitions; each default argument, partial-concept-ids, requires-clause, or noexcept-specifier is a separate
definition which is unrelated to the templated function definition or to any other default arguments partial-
concept-ids, requires-clauses, or noexcept-specifier s. For the purpose of instantiation, the substatements of a
constexpr if statement (9.4.1) are considered definitions.
3
Because an alias-declaration cannot declare a template-id, it is not possible to partially or explicitly specialize
an alias template.
17.6.1
Class templates
[temp.class]
1
A class template defines the layout and operations for an unbounded set of related types.
2
[Example: A single class template List might 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. Similarly, a class template Array
describing a contiguous, dynamic array might 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]; }
};
§ 17.6.1
323
The prefix template<class T> specifies that a template is being declared and that a type-name T may be
used in the declaration. In other words, Array is a parameterized type with T as its parameter.
— end
example ]
3
When a member function, a member class, a member enumeration, a static data member or a member
template of a class template is defined outside of the class template definition, the member definition is defined
as a template definition in which the template-head is equivalent to that of the class template (17.6.6.1).
The names of the template parameters used in the definition of the member may be different from the
template parameter names used in the class template definition. The template argument list following the
class template name in the member definition shall name the parameters in the same order as the one used
in the template parameter list of the member. Each template parameter pack shall be expanded with an
ellipsis in the template argument list. [ Example:
template<class T1, class T2> struct A {
void f1();
void f2();
};
template<class T2, class T1> void A<T2,T1>::f1() { }
// OK
template<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() { }
// OK
template<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-heads match
template<typename T> void S<T>::g() { } // error: no matching declaration for S<T>
template<typename T> requires C<T>
// error (no diagnostic required): template-heads are
void S<T>::h() { }
// functionally equivalent but not equivalent
template<C X> template<D Y>
struct S<X>::Inner { };
// OK
— end example ]
4
In a redeclaration, partial specialization, explicit specialization or explicit instantiation of a class template,
the class-key shall agree in kind with the original class template declaration (10.1.7.3).
17.6.1.1
Member functions of class templates
[temp.mem.func]
1
A member function of a class template may be defined outside of the class template definition in which it is
declared. [ Example:
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 function templates. The subscript function might be defined like this:
§ 17.6.1.1
324
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> { }
// OK
template<typename T>
void S<T>::g() { }
// error: no matching function in S<T>
— end example ]
2
The template-arguments for a member function of a class template are determined by the template-arguments
of the type of the object for which the member function is called. [Example: The template-argument for
Array<T>::operator[]() will be determined by the Array to which the subscripting operation is applied.
Array<int> v1(20);
Array<dcomplex> v2(30);
v1[3] = 7;
// Array<int>::operator[]()
v2[3] = dcomplex(7,8);
// Array<dcomplex>::operator[]()
— end example ]
17.6.1.2
Member classes of class templates
[temp.mem.class]
1
A member class of a class template may be defined outside the class template definition in which it is declared.
[Note: The member class must be defined before its first use that requires an instantiation (17.8.1). For
example,
template<class T> struct A {
class B;
};
A<int>::B* b1;
// OK: requires A to be defined but not A::B
template<class T> class A<T>::B { };
A<int>::B b2;
// OK: requires A::B to be defined
— end note ]
17.6.1.3
Static data members of class templates
[temp.static]
1
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. [ Example:
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 ]
§ 17.6.1.3
325
2
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. [ Example:
template <class T> struct A {
static int i[];
};
template <class T> int A<T>::i[4];
// 4 elements
template <> int A<int>::i[] = { 1 };
// OK: 1 element
— end example ]
17.6.1.4
Enumeration members of class templates
[temp.mem.enum]
1
An enumeration member of a class template may be defined outside the class template definition. [ Example:
template<class T> struct A {
enum E : T;
};
A<int> a;
template<class T> enum A<T>::E : T { e1, e2 };
A<int>::E e = A<int>::e1;
— end example ]
17.6.2
Member templates
[temp.mem]
1
A template can be declared within a class or class template; such a template is called a member template. A
member template can be defined within or outside its class definition or class template definition. A member
template of a class template that is defined outside of its class template definition shall be specified with a
template-head equivalent to that of the class template followed by a template-head equivalent to that of the
member template (17.6.6.1). [ Example:
template<class T> struct string {
template<class T2> int compare(const T2&);
template<class T2> string(const string<T2>& s) { /* ... */ }
};
template<class T> template<class T2> int string<T>::compare(const T2& s) {
}
— end example ] [ Example:
template<typename T> concept C1 = true;
template<typename T> concept C2 = sizeof(T) <= 4;
template<C1 T> struct S {
template<C2 U> void f(U);
template<C2 U> void g(U);
};
template<C1 T> template<C2 U>
void S<T>::f(U) { }
// OK
template<C1 T> template<typename U>
void S<T>::g(U) { }
// error: no matching function in S<T>
— end example ]
2
A local class of non-closure type shall not have member templates. Access control rules (Clause 14) apply
to member template names. A destructor shall not be a member template. A non-template member
function (11.3.5) with a given name and type and a member function template of the same name, which
could be used to generate a specialization of the same type, can both be declared in a class. When both
exist, a use of that name and type refers to the non-template member unless an explicit template argument
list is supplied. [ Example:
template <class T> struct A {
void f(int);
template <class T2> void f(T2);
};
§ 17.6.2
326
template <> void A<int>::f(int) { }
// non-template member function
template <> template <> void A<int>::f<>(int) { }
// member function template specialization
int main() {
A<char> ac;
ac.f(1);
// non-template
ac.f(’c’);
// template
ac.f<>(1);
// template
}
— end example ]
3
A member function template shall not be virtual. [ Example:
template <class T> struct AA {
template <class C> virtual void g(C);
// error
virtual void f();
// OK
};
— end example ]
4
A specialization of a member function template does not override a virtual function from a base class.
[ Example:
class B {
virtual void f(int);
};
class D : public B {
template <class T> void f(T); // does not override B::f(int)
void f(int i) { f<>(i); }
// overriding function that calls the template instantiation
};
— end example ]
5
A specialization of a conversion function template is referenced in the same way as a non-template conversion
function that converts to the same type. [ Example:
struct A {
template <class T> operator T*();
};
template <class T> A::operator T*(){ return 0; }
template <> A::operator char*(){ return 0; }
// specialization
template A::operator void*();
// explicit instantiation
int main() {
A a;
int* ip;
ip = a.operator int*();
// explicit call to template operator A::operator int*()
}
— end example ] [ Note: Because the explicit template argument list follows the function template name, and
because conversion member function templates and constructor member function templates are called without
using a function name, there is no way to provide an explicit template argument list for these function
templates.
— end note ]
6
A specialization of a conversion function template is not found by name lookup. Instead, any conversion
function templates visible in the context of the use are considered. For each such operator, if argument
deduction succeeds (17.9.2.3), the resulting specialization is used as if found by name lookup.
7
A using-declaration in a derived class cannot refer to a specialization of a conversion function template in a
base class.
8
Overload resolution (16.3.3.2) and partial ordering (17.6.6.2) are used to select the best conversion function
among multiple specializations of conversion function templates and/or non-template conversion functions.
17.6.3
Variadic templates
[temp.variadic]
1
A template parameter pack is a template parameter that accepts zero or more template arguments. [ Example:
template<class ... Types> struct Tuple { };
§ 17.6.3
327
Tuple<> t0;
// Types contains no arguments
Tuple<int> t1;
// Types contains one argument: int
Tuple<int, float> t2;
// Types contains two arguments: int and float
Tuple<0> error;
// error: 0 is not a type
— end example ]
2
A function parameter pack is a function parameter that accepts zero or more function arguments. [ Example:
template<class ... Types> void f(Types ... args);
f();
// OK: args contains no arguments
f(1);
// OK: args contains one argument: int
f(2, 1.0);
// OK: args contains two arguments: int and double
— end example ]
3
A parameter pack is either a template parameter pack or a function parameter pack.
4
A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more
instantiations of the pattern in a list (described below). The form of the pattern depends on the context in
which the expansion occurs. Pack expansions can occur in the following contexts:
(4.1)
In a function parameter pack (11.3.5); the pattern is the parameter-declaration without the ellipsis.
(4.2)
In a using-declaration (10.3.3); the pattern is a using-declarator.
(4.3)
In a template parameter pack that is a pack expansion (17.1):
(4.3.1)
if the template parameter pack is a parameter-declaration; the pattern is the parameter-declaration
without the ellipsis;
(4.3.2)
if the template parameter pack is a type-parameter with a template-parameter-list; the pattern is
the corresponding type-parameter without the ellipsis.
(4.4)
In an initializer-list (11.6); the pattern is an initializer-clause.
(4.5)
In a base-specifier-list (Clause 13); the pattern is a base-specifier.
(4.6)
In a mem-initializer-list (15.6.2) for a mem-initializer whose mem-initializer-id denotes a base class;
the pattern is the mem-initializer.
(4.7)
In a template-argument-list (17.3); the pattern is a template-argument.
(4.8)
In an attribute-list (10.6.1); the pattern is an attribute.
(4.9)
In an alignment-specifier (10.6.2); the pattern is the alignment-specifier without the ellipsis.
(4.10)
In a capture-list (8.4.5); the pattern is a capture.
(4.11)
In a sizeof... expression (8.5.2.3); the pattern is an identifier.
(4.12)
In a fold-expression (8.4.6); the pattern is the cast-expression that contains an unexpanded parameter
pack.
[ Example:
template<class ... Types> void f(Types ... rest);
template<class ... Types> void g(Types ... rest) {
f(&rest ...);
// “&rest ...” is a pack expansion; “&rest” is its pattern
}
— end example ]
5
For the purpose of determining whether a parameter pack satisfies a rule regarding entities other than
parameter packs, the parameter pack is considered to be the entity that would result from an instantiation of
the pattern in which it appears.
6
A parameter pack whose name appears within the pattern of a pack expansion is expanded by that pack
expansion. An appearance of the name of a parameter pack is only expanded by the innermost enclosing pack
expansion. The pattern of a pack expansion shall name one or more parameter packs that are not expanded
by a nested pack expansion; such parameter packs are called unexpanded parameter packs in the pattern. All
of the parameter packs expanded by a pack expansion shall have the same number of arguments specified.
An appearance of a name of a parameter pack that is not expanded is ill-formed. [ Example:
template<typename...> struct Tuple {};
§ 17.6.3
328
template<typename T1, typename T2> struct Pair {};
template<class ... Args1> struct zip {
template<class ... Args2> struct with {
typedef Tuple<Pair<Args1, Args2> ... > type;
};
};
typedef zip<short, int>::with<unsigned short, unsigned>::type T1;
// T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>>
typedef zip<short>::with<unsigned short, unsigned>::type T2;
// error: different number of arguments specified for Args1 and Args2
template<class ... Args>
void g(Args ... args) {
// OK: Args is expanded by the function parameter pack args
f(const_cast<const Args*>(&args)...);
// OK: “Args” and “args” are expanded
f(5 ...);
// error: pattern does not contain any parameter packs
f(args);
// error: parameter pack “args” is not expanded
f(h(args ...) + args ...);
// OK: first “args” expanded within h,
// second “args” expanded within f
}
— end example ]
7
The instantiation of a pack expansion that is neither a sizeof... expression nor a fold-expression produces a
list E1, E2, . . . , EN , where N is the number of elements in the pack expansion parameters. Each Ei is generated
by instantiating the pattern and replacing each pack expansion parameter with its ith element. Such an
element, in the context of the instantiation, is interpreted as follows:
(7.1)
if the pack is a template parameter pack, the element is a template parameter (17.1) of the corresponding
kind (type or non-type) designating the type or value from the template argument; otherwise,
(7.2)
if the pack is a function parameter pack, the element is an id-expression designating the function
parameter that resulted from the instantiation of the pattern where the pack is declared.
All of the Ei become elements in the enclosing list.
[Note: The variety of list varies with the context:
expression-list, base-specifier-list, template-argument-list, etc. — end note ] When N is zero, the instantiation
of the expansion produces an empty list. Such an instantiation does not alter the syntactic interpretation of
the enclosing construct, even in cases where omitting the list entirely would otherwise be ill-formed or would
result in an ambiguity in the grammar. [ Example:
template<class... T> struct X : T... { };
template<class... T> void f(T... values) {
X<T...> x(values...);
}
template void f<>();
// OK: X<> has no base classes
// x is a variable of type X<> that is value-initialized
— end example ]
8
The instantiation of a sizeof... expression (8.5.2.3) produces an integral constant containing the number
of elements in the parameter pack it expands.
9
The instantiation of a fold-expression produces:
(9.1)
((E1 op E2) op · · · ) op EN for a unary left fold,
(9.2)
E1 op (··· op (EN−1 op EN )) for a unary right fold,
(9.3)
(((E op E1) op E2) op · · · ) op EN for a binary left fold, and
(9.4)
E1 op (··· op (EN−1 op (EN op E))) for a binary right fold.
In each case, op is the fold-operator, N is the number of elements in the pack expansion parameters, and
each Ei is generated by instantiating the pattern and replacing each pack expansion parameter with its ith
element. For a binary fold-expression, E is generated by instantiating the cast-expression that did not contain
an unexpanded parameter pack. [ Example:
template<typename ...Args>
bool all(Args ...args) { return (... && args); }
§ 17.6.3
329
bool b = all(true, true, true, false);
Within the instantiation of all, the returned expression expands to ((true && true) && true) && false,
which evaluates to false.
— end example ] If N is zero for a unary fold-expression, the value of the expression
is shown in Table 14; if the operator is not listed in Table 14, the instantiation is ill-formed.
Table 14 — Value of folding empty sequences
Operator Value when parameter pack is empty
&&
true
||
false
,
void()
17.6.4
Friends
[temp.friend]
1
A friend of a class or class template can be a function template or class template, a specialization of a
function template or class template, or a non-template function or class. For a friend function declaration
that is not a template declaration:
(1.1)
if the name of the friend is a qualified or unqualified template-id, the friend declaration refers to a
specialization of a function template, otherwise,
(1.2)
if the name of the friend is a qualified-id and a matching non-template function is found in the specified
class or namespace, the friend declaration refers to that function, otherwise,
(1.3)
if the name of the friend is a qualified-id and a matching function template is found in the specified class or
namespace, the friend declaration refers to the deduced specialization of that function template (17.9.2.6),
otherwise,
(1.4)
the name shall be an unqualified-id that declares (or redeclares) a non-template function.
[ Example:
template<class T> class task;
template<class T> task<T>* preempt(task<T>*);
template<class T> class task {
friend void next_time();
friend void process(task<T>*);
friend task<T>* preempt<T>(task<T>*);
template<class C> friend int func(C);
friend class task<int>;
template<class P> friend class frd;
};
Here, each specialization of the task class template has the function next_time as a friend; because process
does not have explicit template-arguments, each specialization of the task class template has an appropriately
typed function process as a friend, and this friend is not a function template specialization; because the
friend preempt has an explicit template-argument T, each specialization of the task class template has the
appropriate specialization of the function template preempt as a friend; and each specialization of the task
class template has all specializations of the function template func as friends. Similarly, each specialization of
the task class template has the class template specialization task<int> as a friend, and has all specializations
of the class template frd as friends.
— end example ]
2
A friend template may be declared within a class or class template. A friend function template may be
defined within a class or class template, but a friend class template may not be defined in a class or class
template. In these cases, all specializations of the friend class or friend function template are friends of the
class or class template granting friendship. [ Example:
class A {
template<class T> friend class B;
// OK
template<class T> friend void f(T){ /* ... */ }
// OK
};
— end example ]
§ 17.6.4
330
3
A template friend declaration specifies that all specializations of that template, whether they are implicitly
instantiated (17.8.1), partially specialized (17.6.5) or explicitly specialized (17.8.3), are friends of the class
containing the template friend declaration. [ Example:
class X {
template<class T> friend struct A;
class Y { };
};
template<class T> struct A { X::Y ab; };
// OK
template<class T> struct A<T*> { X::Y ab; };
// OK
— end example ]
4
A template friend declaration may declare a member of a dependent type to be a friend. The friend
declaration shall declare a function or specify a type with an elaborated-type-specifier, in either case with a
nested-name-specifier ending with a simple-template-id, C, whose template-name names a class template. The
template parameters of the template friend declaration shall be deducible from C (17.9.2.5). In this case, a
member of a specialization S of the class template is a friend of the class granting friendship if deduction
of the template parameters of C from S succeeds, and substituting the deduced template arguments into
the friend declaration produces a declaration that would be a valid redeclaration of the member of the
specialization. [ Example:
template<class T> struct A {
struct B { };
void f();
struct D {
void g();
};
T h();
template<T U> T i();
};
template<> struct A<int> {
struct B { };
int f();
struct D {
void g();
};
template<int U> int i();
};
template<> struct A<float*> {
int *h();
};
class C {
template<class T> friend struct A<T>::B;
// grants friendship to A<int>::B even though
// it is not a specialization of A<T>::B
template<class T> friend void A<T>::f();
// does not grant friendship to A<int>::f()
// because its return type does not match
template<class T> friend void A<T>::D::g();
// ill-formed: A<T>::D does not end with
// a simple-template-id
template<class T> friend int *A<T*>::h();
// grants friendship to A<int*>::h() and A<float*>::h()
template<class T> template<T U>
// grants friendship to instantiations of A<T>::i() and
friend T A<T>::i();
// to A<int>::i(), and thereby to all specializations
};
// of those function templates
— end example ]
5
[Note: A friend declaration may first declare a member of an enclosing namespace scope (17.7.5).
— end
note ]
6
A friend template shall not be declared in a local class.
7
Friend declarations shall not declare partial specializations. [ Example:
template<class T> class A { };
§ 17.6.4
331
class X {
template<class T> friend class A<T*>;
// error
};
— end example ]
8
When a friend declaration refers to a specialization of a function template, the function parameter declarations
shall not include default arguments, nor shall the inline specifier be used in such a declaration.
9
A non-template friend declaration shall not have a requires-clause.
17.6.5
Class template partial specializations
[temp.class.spec]
1
A primary class template declaration is one in which the class template name is an identifier. A template
declaration in which the class template name is a simple-template-id is a partial specialization of the class
template named in the simple-template-id. A partial specialization of a class template provides an alternative
definition of the template that is used instead of the primary definition when the arguments in a specialization
match those given in the partial specialization (17.6.5.1). The primary template shall be declared before
any specializations of that template. A partial specialization shall be declared before the first use of a class
template specialization that would make use of the partial specialization as the result of an implicit or explicit
instantiation in every translation unit in which such a use occurs; no diagnostic is required.
2
Each class template partial specialization is a distinct template and definitions shall be provided for the
members of a template partial specialization (17.6.5.3).
3
[ 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> { };
The first declaration declares the primary (unspecialized) class template. The second and subsequent
declarations declare partial specializations of the primary template.
— end example ]
4
A class template partial specialization may be constrained (Clause 17). [ Example:
template<typename T> concept C = true;
template<typename T> struct X { };
template<typename T> struct X<T*> { };
// #1
template<C T> struct X<T> { };
// #2
Both partial specializations are more specialized than the primary template. #1 is more specialized because
the deduction of its template arguments from the template argument list of the class template specialization
succeeds, while the reverse does not. #2 is more specialized because the template arguments are equivalent,
but the partial specialization is more constrained (17.4.4).
— end example ]
5
The template parameters are specified in the angle bracket enclosed list that immediately follows the keyword
template. For partial specializations, the template argument list is explicitly written immediately following
the class template name. For primary templates, this list is implicitly described by the template parameter
list. Specifically, the order of the template arguments is the sequence in which they appear in the template
parameter list. [ Example: The template argument list for the primary template in the example above is <T1,
T2, I>.
— end example ] [ Note: The template argument list shall not be specified in the primary template
declaration. For example,
template<class T1, class T2, int I>
class A<T1, T2, I> { };
// error
— end note ]
6
A class template partial specialization may be declared in any scope in which the corresponding primary
template may be defined (10.3.1.2, 12.2, 17.6.2). [ Example:
template<class T> struct A {
struct C {
template<class T2> struct B { };
template<class T2> struct B<T2**> { };
// partial specialization #1
};
};
§ 17.6.5
332
// 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 ]
7
Partial specialization declarations themselves are not found by name lookup. Rather, when the primary
template name is used, any previously-declared partial specializations of the primary template are also
considered. One consequence is that a using-declaration which refers to a class template does not restrict the
set of partial specializations which may be found through the 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 ]
8
A non-type argument is non-specialized if it is the name of a non-type parameter. All other non-type
arguments are specialized.
9
Within the argument list of a class template partial specialization, the following restrictions apply:
(9.1)
The type of a template parameter corresponding to a specialized non-type argument shall not be
dependent on a parameter of the specialization. [ 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 ]
(9.2)
The specialization shall be more specialized than the primary template (17.6.5.2).
(9.3)
The template parameter list of a specialization shall not contain default template argument values.141
(9.4)
An argument shall not contain an unexpanded parameter pack. If an argument is a pack expansion
(17.6.3), it shall be the last argument in the template argument list.
10
The usual access checking rules do not apply to non-dependent names used to specify template arguments of
the simple-template-id of the partial specialization. [Note: The template arguments may be private types
or objects that would normally not be accessible. Dependent names cannot be checked when declaring the
partial specialization, but will be checked when substituting into the partial specialization.
— end note ]
17.6.5.1
Matching of class template partial specializations
[temp.class.spec.match]
1
When a class template is used in a context that requires an instantiation of the class, it is necessary to
determine whether the instantiation is to be generated using the primary template or one of the partial
specializations. This is done by matching the template arguments of the class template specialization with
the template argument lists of the partial specializations.
(1.1)
If exactly one matching specialization is found, the instantiation is generated from that specialization.
(1.2)
If more than one matching specialization is found, the partial order rules (17.6.5.2) are used to determine
whether one of the specializations is more specialized than the others. If none of the specializations is
more specialized than all of the other matching specializations, then the use of the class template is
ambiguous and the program is ill-formed.
141) There is no way in which they could be used.
§ 17.6.5.1
333
(1.3)
If no matches are found, the instantiation is generated from the primary template.
2
A partial specialization matches a given actual template argument list if the template arguments of the partial
specialization can be deduced from the actual template argument list (17.9.2), and the deduced template
arguments satisfy the associated constraints of the partial specialization, if any (17.4.2). [ 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 ] [ Example:
template<typename T> concept C = requires (T t) { t.f(); };
template<typename T> struct S { };
// #1
template<C T> struct S<T> { };
// #2
struct Arg { void f(); };
S<int> s1;
// uses #1; the constraints of #2 are not satisfied
S<Arg> s2;
// uses #2; both constraints are satisfied but #2 is more specialized
— end example ]
3
If the template arguments of a partial specialization cannot be deduced because of the structure of its
template-parameter-list and the template-id, the program is ill-formed. [ 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 ]
4
In a type name that refers to a class template specialization, (e.g., A<int, int, 1>) the argument list shall
match the template parameter list of the primary template. The template arguments of a specialization are
deduced from the arguments of the primary template.
17.6.5.2
Partial ordering of class template specializations
[temp.class.order]
1
For two class template partial specializations, the first is more specialized than the second if, given the
following rewrite to two function templates, the first function template is more specialized than the second
according to the ordering rules for function templates (17.6.6.2):
(1.1)
Each of the two function templates has the same template parameters and associated constraints (17.4.2)
as the corresponding partial specialization.
(1.2)
Each function template has a single function parameter whose type is a class template specialization
where the template arguments are the corresponding template parameters from the function template
for each template argument in the template-argument-list of the simple-template-id of the partial
specialization.
2
[ 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
§ 17.6.5.2
334
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
According to the ordering rules for function templates, the function template B is more specialized than
the function template A and the function template D is more specialized than the function template C.
Therefore, the partial specialization #2 is more specialized than the partial specialization #1 and the partial
specialization #4 is more specialized than the partial specialization #3.
— end example ] [ Example:
template<typename T> concept C = requires (T t) { t.f(); };
template<typename T> concept D = C<T> && requires (T t) { t.f(); };
template<typename T> class S { };
template<C T> class S<T> { };
// #1
template<D T> class S<T> { };
// #2
template<C T> void f(S<T>);
// A
template<D T> void f(S<T>);
// B
The partial specialization #2 is more specialized than #1 because B is more specialized than A. — end
example ]
17.6.5.3
Members of class template specializations
[temp.class.spec.mfunc]
1
The template parameter list of a member of a class template partial specialization shall match the template
parameter list of the class template partial specialization. The template argument list of a member of a
class template partial specialization shall match the template argument list of the class template partial
specialization. A class template specialization is a distinct template. The members of the class template partial
specialization are unrelated to the members of the primary template. Class template partial specialization
members that are used in a way that requires a definition shall be defined; the definitions of members of the
primary template are never used as definitions for members of a class template partial specialization. An
explicit specialization of a member of a class template partial specialization is declared in the same way as
an explicit specialization of the primary template. [ 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
}
§ 17.6.5.3
335
— end example ]
2
If a member template of a class template is partially specialized, the member template partial specializations
are member templates of the enclosing class template; if the enclosing class template is instantiated (17.8.1,
17.8.2), a declaration for every member template partial specialization is also instantiated as part of creating
the members of the class template specialization. If the primary member template is explicitly specialized for
a given (implicit) specialization of the enclosing class template, the partial specializations of the member
template are ignored for this specialization of the enclosing class template. If a partial specialization of the
member template is explicitly specialized for a given (implicit) specialization of the enclosing class template,
the primary member template and its other partial specializations are still considered for this specialization
of the enclosing class template. [ 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 ]
17.6.6
Function templates
[temp.fct]
1
A function template defines an unbounded set of related functions. [Example: A family of sort functions
might be declared like this:
template<class T> class Array { };
template<class T> void sort(Array<T>&);
— end example ]
2
A function template can be overloaded with other function templates and with non-template functions (11.3.5).
A non-template function is not related to a function template (i.e., it is never considered to be a specialization),
even if it has the same name and type as a potentially generated function template specialization.142
17.6.6.1
Function template overloading
[temp.over.link]
1
It is possible to overload function templates so that two different function template specializations have the
same type. [ Example:
// translation unit 1:
// translation unit 2:
template<class T>
template<class T>
void f(T*);
void f(T);
void g(int* p) {
void h(int* p) {
f(p); // calls f<int>(int*)
f(p); // calls f<int*>(int*)
}
}
— end example ]
2
Such specializations are distinct functions and do not violate the one-definition rule (6.2).
3
The signature of a function template is defined in Clause 3. The names of the template parameters are
significant only for establishing the relationship between the template parameters and the rest of the signature.
[Note: Two distinct function templates may have identical function return types and function parameter
lists, even if overload resolution alone cannot distinguish them.
template<class T> void f();
template<int I> void f();
// OK: overloads the first template
// distinguishable with an explicit template argument list
— end note ]
142) That is, declarations of non-template functions do not merely guide overload resolution of function template specializations
with the same name. If such a non-template function is odr-used (6.2) in a program, it must be defined; it will not be implicitly
instantiated using the function template definition.
§ 17.6.6.1
336
4
When an expression that references a template parameter is used in the function parameter list or the return
type in the declaration of a function template, the expression that references the template parameter is part
of the signature of the function template. This is necessary to permit a declaration of a function template in
one translation unit to be linked with another declaration of the function template in another translation
unit and, conversely, to ensure that function templates that are intended to be distinct are not linked with
one another. [ Example:
template <int I, int J> A<I+J> f(A<I>, A<J>);
// #1
template <int K, int L> A<K+L> f(A<K>, A<L>);
// same as #1
template <int I, int J> A<I-J> f(A<I>, A<J>);
// different from #1
— end example ] [ Note: Most expressions that use template parameters use non-type template parameters,
but it is possible for an expression to reference a type parameter. For example, a template type parameter
can be used in the sizeof operator.
— end note ]
5
Two expressions involving template parameters are considered equivalent if two function definitions containing
the expressions would satisfy the one-definition rule (6.2), except that the tokens used to name the template
parameters may differ as long as a token used to name a template parameter in one expression is replaced by
another token that names the same template parameter in the other expression. Two lambda-expressions are
never considered equivalent. [ Note: The intent is to avoid lambda-expressions appearing in the signature of a
function template with external linkage.
— end note ] For determining whether two dependent names (17.7.2)
are equivalent, only the name itself is considered, not the result of name lookup in the context of the template.
If multiple declarations of the same function template differ in the result of this name lookup, the result for
the first declaration is used. [ Example:
template <int I, int J> void f(A<I+J>);
// #1
template <int K, int L> void f(A<K+L>);
// same as #1
template <class T> decltype(g(T())) h();
int g(int);
template <class T> decltype(g(T())) h()
// redeclaration of h() uses the earlier lookup. . .
{ return g(T()); }
// . . . although the lookup here does find g(int)
int i = h<int>();
// template argument substitution fails; g(int)
// was not in scope at the first declaration of h()
// ill-formed, no diagnostic required: the two expressions are functionally equivalent but not equivalent
template <int N> void foo(const char (*s)[([]{}, N)]);
template <int N> void foo(const char (*s)[([]{}, N)]);
// two different declarations because the non-dependent portions are not considered equivalent
template <class T> void spam(decltype([]{}) (*s)[sizeof(T)]);
template <class T> void spam(decltype([]{}) (*s)[sizeof(T)]);
— end example ] Two expressions involving template parameters that are not equivalent are functionally
equivalent if, for any given set of template arguments, the evaluation of the expression results in the same
value.
6
Two template-heads are equivalent if their template-parameter-lists have the same length, corresponding
template-parameter s are equivalent, and if either has a requires-clause, they both have requires-clauses and
the corresponding constraint-expressions are equivalent. Two template-parameter s are equivalent under the
following conditions:
(6.1)
they declare template parameters of the same kind,
(6.2)
if either declares a template parameter pack, they both do,
(6.3)
if they declare non-type template parameters, they have equivalent types,
(6.4)
if they declare template template parameters, their template parameters are equivalent, and
(6.5)
if either is declared with a qualified-concept-name, they both are, and the qualified-concept-names are
equivalent.
When determining whether types or qualified-concept-names are equivalent, the rules above are used to
compare expressions involving template parameters. Two template-heads are functionally equivalent if they
accept and are satisfied by (17.4.1) the same set of template argument lists.
7
Two function templates are equivalent if they are declared in the same scope, have the same name, have
equivalent template-heads, and have return types, parameter lists, and trailing requires-clauses (if any) that
§ 17.6.6.1
337
are equivalent using the rules described above to compare expressions involving template parameters. Two
function templates are functionally equivalent if they are declared in the same scope, have the same name,
accept and are satisfied by the same set of template argument lists, and have return types and parameter lists
that are functionally equivalent using the rules described above to compare expressions involving template
parameters. If the validity or meaning of the program depends on whether two constructs are equivalent,
and they are functionally equivalent but not equivalent, the program is ill-formed, no diagnostic required.
8
[ Note: This rule guarantees that equivalent declarations will be linked with one another, while not requiring
implementations to use heroic efforts to guarantee that functionally equivalent declarations will be treated as
distinct. For example, the last two declarations are functionally equivalent and would cause a program to be
ill-formed:
// guaranteed to be the same
template <int I> void f(A<I>, A<I+10>);
template <int I> void f(A<I>, A<I+10>);
// guaranteed to be different
template <int I> void f(A<I>, A<I+10>);
template <int I> void f(A<I>, A<I+11>);
// ill-formed, no diagnostic required
template <int I> void f(A<I>, A<I+10>);
template <int I> void f(A<I>, A<I+1+2+3+4>);
— end note ]
17.6.6.2
Partial ordering of function templates
[temp.func.order]
1
If a function template is overloaded, the use of a function template specialization might be ambiguous because
template argument deduction (17.9.2) may associate the function template specialization with more than one
function template declaration. Partial ordering of overloaded function template declarations is used in the
following contexts to select the function template to which a function template specialization refers:
(1.1)
during overload resolution for a call to a function template specialization (16.3.3);
(1.2)
when the address of a function template specialization is taken;
(1.3)
when a placement operator delete that is a function template specialization is selected to match a
placement operator new (6.6.4.4.2, 8.5.2.4);
(1.4)
when a friend function declaration (17.6.4), an explicit instantiation (17.8.2) or an explicit specialization
(17.8.3) refers to a function template specialization.
2
Partial ordering selects which of two function templates is more specialized than the other by transforming
each template in turn (see next paragraph) and performing template argument deduction using the function
type. The deduction process determines whether one of the templates is more specialized than the other.
If so, the more specialized template is the one chosen by the partial ordering process. If both deductions
succeed, the partial ordering selects the more constrained template as described by the rules in 17.4.4.
3
To produce the transformed template, for each type, non-type, or template template parameter (including
template parameter packs (17.6.3) thereof) synthesize a unique type, value, or class template respectively
and substitute it for each occurrence of that parameter in the function type of the template. [ Note: The
type replacing the placeholder in the type of the value synthesized for a non-type template parameter is also
a unique synthesized type.
— end note ] If only one of the function templates M is a non-static member of
some class A, M is considered to have a new first parameter inserted in its function parameter list. Given cv
as the cv-qualifiers of M (if any), the new parameter is of type “rvalue reference to cv A” if the optional
ref-qualifier of M is && or if M has no ref-qualifier and the first parameter of the other template has rvalue
reference type. Otherwise, the new parameter is of type “lvalue reference to cv A”. [Note: This allows a
non-static member to be ordered with respect to a non-member function and for the results to be equivalent
to the ordering of two equivalent non-members.
— end note ] [ Example:
struct A { };
template<class T> struct B {
template<class R> int operator*(R&);
// #1
};
template<class T, class R> int operator*(T&, R&);
// #2
§ 17.6.6.2
338
// The declaration of B::operator* is transformed into the equivalent of
// template<class R> int operator*(B<A>&, R&);
// #1a
int main() {
A a;
B<A> b;
b * a;
// calls #1a
}
— end example ]
4
Using the transformed function template’s function type, perform type deduction against the other template
as described in 17.9.2.4.
[ Example:
template<class T> struct A { A(); };
template<class T> void f(T);
template<class T> void f(T*);
template<class T> void f(const T*);
template<class T> void g(T);
template<class T> void g(T&);
template<class T> void h(const T&);
template<class T> void h(A<T>&);
void m() {
const int* p;
f(p);
// f(const T*) is more specialized than f(T) or f(T*)
float x;
g(x);
// ambiguous: g(T) or g(T&)
A<int> z;
h(z);
// overload resolution selects h(A<T>&)
const A<int> z2;
h(z2);
// h(const T&) is called because h(A<T>&) is not callable
}
— end example ]
5
[Note: Since partial ordering in a call context considers only parameters for which there are explicit
call arguments, some parameters are ignored (namely, function parameter packs, parameters with default
arguments, and ellipsis parameters). [ Example:
template<class T> void f(T);
// #1
template<class T> void f(T*, int=1);
// #2
template<class T> void g(T);
// #3
template<class T> void g(T*, ...);
// #4
int main() {
int* ip;
f(ip);
// calls #2
g(ip);
// calls #4
}
— end example ] [ Example:
template<class T, class U> struct A { };
template<class T, class U> void f(U, A<U, T>* p = 0);
// #1
template<
class U> void f(U, A<U, U>* p = 0);
// #2
template<class T
> void g(T, T = T());
// #3
template<class T, class... U> void g(T, U ...);
// #4
void h() {
f<int>(42, (A<int, int>*)0);
// calls #2
f<int>(42);
// error: ambiguous
§ 17.6.6.2
339
g(42);
// error: ambiguous
}
— end example ] [ Example:
template<class T, class... U> void f(T, U...);
// #1
template<class T
> void f(T);
// #2
template<class T, class... U> void g(T*, U...);
// #3
template<class T
> void g(T);
// #4
void h(int i) {
f(&i);
// error: ambiguous
g(&i);
// OK: calls #3
}
— end example ] — end note ]
17.6.7
Alias templates
[temp.alias]
1
A template-declaration in which the declaration is an alias-declaration (Clause 10) declares the identifier to
be an alias template. An alias template is a name for a family of types. The name of the alias template is a
template-name.
2
When a template-id refers to the specialization of an alias template, it is equivalent to the associated type
obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias
template. [ Note: An alias template name is never deduced. — end note ]
[ Example:
template<class T> struct Alloc { /* ... */ };
template<class T> using Vec = vector<T, Alloc<T>>;
Vec<int> v;
// same as vector<int, Alloc<int>> v;
template<class T>
void process(Vec<T>& v)
{ /* ... */ }
template<class T>
void process(vector<T, Alloc<T>>& w)
{ /* ... */ }
// error: redefinition
template<template<class> class TT>
void f(TT<int>);
f(v);
// error: Vec not deduced
template<template<class,class> class TT>
void g(TT<int, Alloc<int>>);
g(v);
// OK: TT = vector
— end example ]
3
However, if the template-id is dependent, subsequent template argument substitution still applies to the
template-id. [ Example:
template<typename...> using void_t = void;
template<typename T> void_t<typename T::foo> f();
f<int>();
// error, int does not have a nested type foo
— end example ]
4
The type-id in an alias template declaration shall not refer to the alias template being declared. The type
produced by an alias template specialization shall not directly or indirectly make use of that specialization.
[ Example:
template <class T> struct A;
template <class T> using B = typename A<T>::U;
template <class T> struct A {
typedef B<T> U;
};
B<short> b;
// error: instantiation of B<short> uses own type via A<short>::U
§ 17.6.7
340
— end example ]
5
The type of a lambda expression appearing in an alias template declaration is different between instantiations
of that template, even when the lambda expression is not dependent. [ Example:
template <class T>
using A = decltype([] { });
// A<int> and A<char> refer to different closure types
— end example ]
17.6.8
Concept definitions
[temp.concept]
1
A concept is a template that defines constraints on its template arguments.
2
A concept-definition declares a concept. Its identifier becomes a concept-name referring to that concept
within its scope. [ Example:
template<typename T>
concept C = requires(T x) {
{ x == x } -> bool;
};
template<typename T>
requires C<T>
// C constrains f1(T) in constraint-expression
T f1(T x) { return x; }
template<C T>
// C constrains f2(T) as a constrained-parameter
T f2(T x) { return x; }
— end example ]
3
A concept-definition shall appear at namespace scope (6.3.6).
4
A concept shall not have associated constraints (17.4.2).
5
A concept is not instantiated (17.8). A program that explicitly instantiates (17.8.2), explicitly specializes
(17.8.3), or partially specializes a concept is ill-formed.
[Note: An id-expression that denotes a concept
specialization is evaluated as an expression (8.4.4).
— end note ]
6
The first declared template parameter of a concept definition is its prototype parameter. A variadic concept
is a concept whose prototype parameter is a template parameter pack.
17.7
Name resolution
[temp.res]
1
Three kinds of names can be used within a template definition:
(1.1)
The name of the template itself, and names declared within the template itself.
(1.2)
Names dependent on a template-parameter (17.7.2).
(1.3)
Names from scopes which are visible within the template definition.
2
A name used in a template declaration or definition and that is dependent on a template-parameter is assumed
not to name a type unless the applicable name lookup finds a type name or the name is qualified by the
keyword typename. [ Example:
// no B declared here
class X;
template<class T> class Y {
class Z;
// forward declaration of member class
void f() {
X* a1;
// declare pointer to X
T* a2;
// declare pointer to T
Y* a3;
// declare pointer to Y<T>
Z* a4;
// declare pointer to Z
typedef typename T::A TA;
TA* a5;
// declare pointer to T’s A
typename T::A* a6;
// declare pointer to T’s A
T::A* a7;
// T::A is not a type name:
§ 17.7
341
// multiplication of T::A by a7; ill-formed, no visible declaration of a7
B* a8;
// B is not a type name:
// multiplication of B by a8; ill-formed, no visible declarations of B and a8
}
};
— end example ]
3
When a qualified-id is intended to refer to a type that is not a member of the current instantiation (17.7.2.1)
and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename,
forming a typename-specifier. If the qualified-id in a typename-specifier does not denote a type or a class
template, the program is ill-formed.
typename-specifier:
typename nested-name-specifier identifier
typename nested-name-specifier templateopt simple-template-id
4
If a specialization of a template is instantiated for a set of template-arguments such that the qualified-id
prefixed by typename does not denote a type or a class template, the specialization is ill-formed. The usual
qualified name lookup (6.4.3) is used to find the qualified-id even in the presence of typename. [ Example:
struct A {
struct X { };
int X;
};
struct B {
struct X { };
};
template<class T> void f(T t) {
typename T::X x;
}
void foo() {
A a;
B b;
f(b);
// OK: T::X refers to B::X
f(a);
// error: T::X refers to the data member A::X not the struct A::X
}
— end example ]
5
A qualified name used as the name in a class-or-decltype (Clause 13) or an elaborated-type-specifier is
implicitly assumed to name a type, without the use of the typename keyword. In a nested-name-specifier
that immediately contains a nested-name-specifier that depends on a template parameter, the identifier or
simple-template-id is implicitly assumed to name a type, without the use of the typename keyword. [ Note:
The typename keyword is not permitted by the syntax of these constructs.
— end note ]
6
If, for a given set of template arguments, a specialization of a template is instantiated that refers to a
qualified-id that denotes a type or a class template, and the qualified-id refers to a member of an unknown
specialization, the qualified-id shall either be prefixed by typename or shall be used in a context in which it
implicitly names a type as described above. [ Example:
template <class T> void f(int i) {
T::x * i;
// T::x must not be a type
}
struct Foo {
typedef int x;
};
struct Bar {
static int const x = 5;
};
int main() {
f<Bar>(1);
// OK
f<Foo>(1);
// error: Foo::x is a type
}
§ 17.7
342
— end example ]
7
Within the definition of a class template or within the definition of a member of a class template following
the declarator-id, the keyword typename is not required when referring to the name of a previously declared
member of the class template that declares a type or a class template. [ Note: Such names can be found
using unqualified name lookup (6.4.1), class member lookup (6.4.3.1) into the current instantiation (17.7.2.1),
or class member access expression lookup (6.4.5) when the type of the object expression is the current
instantiation (17.7.2.2).
— end note ] [ Example:
template<class T> struct A {
typedef int B;
B b;
// OK, no typename required
};
— end example ]
8
Knowing which names are type names allows the syntax of every template to be checked. The program is
ill-formed, no diagnostic required, if:
(8.1)
no valid specialization can be generated for a template or a substatement of a constexpr if statement
(9.4.1) within a template and the template is not instantiated, or
(8.2)
no substitution of template arguments into a partial-concept-id or requires-clause would result in a
valid expression, or
(8.3)
every valid specialization of a variadic template requires an empty template parameter pack, or
(8.4)
a hypothetical instantiation of a template immediately following its definition would be ill-formed due
to a construct that does not depend on a template parameter, or
(8.5)
the interpretation of such a construct in the hypothetical instantiation is different from the interpretation
of the corresponding construct in any actual instantiation of the template. [ Note: This can happen in
situations including the following:
(8.5.1)
a type used in a non-dependent name is incomplete at the point at which a template is defined
but is complete at the point at which an instantiation is performed, or
(8.5.2)
lookup for a name in the template definition found a using-declaration, but the lookup in the
corresponding scope in the instantiation does not find any declarations because the using-declaration
was a pack expansion and the corresponding pack is empty, or
(8.5.3)
an instantiation uses a default argument or default template argument that had not been defined
at the point at which the template was defined, or
(8.5.4)
constant expression evaluation (8.6) within the template instantiation uses
(8.5.4.1)
the value of a const object of integral or unscoped enumeration type or
(8.5.4.2)
the value of a constexpr object or
(8.5.4.3)
the value of a reference or
(8.5.4.4)
the definition of a constexpr function,
and that entity was not defined when the template was defined, or
(8.5.5)
a class template specialization or variable template specialization that is specified by a non-
dependent simple-template-id is used by the template, and either it is instantiated from a partial
specialization that was not defined when the template was defined or it names an explicit
specialization that was not declared when the template was defined.
— end note ]
Otherwise, no diagnostic shall be issued for a template for which a valid specialization can be generated.
[Note: If a template is instantiated, errors will be diagnosed according to the other rules in this document.
Exactly when these errors are diagnosed is a quality of implementation issue.
— end note ] [ Example:
int j;
template<class T> class X {
void f(T t, int i, char* p) {
t = i;
// diagnosed if X::f is instantiated, and the assignment to t is an error
p = i;
// may be diagnosed even if X::f is not instantiated
p = j;
// may be diagnosed even if X::f is not instantiated
}
§ 17.7
343
void g(T t) {
+;
// may be diagnosed even if X::g is not instantiated
}
};
template<class... T> struct A {
void operator++(int, T... t);
// error: too many parameters
};
template<class... T> union X : T... { };
// error: union with base class
template<class... T> struct A : T..., T... { };
// error: duplicate base class
— end example ]
9
When looking for the declaration of a name used in a template definition, the usual lookup rules (6.4.1, 6.4.2)
are used for non-dependent names. The lookup of names dependent on the template parameters is postponed
until the actual template argument is known (17.7.2). [ Example:
#include <iostream>
using namespace std;
template<class T> class Set {
T* p;
int cnt;
public:
Set();
Set<T>(const Set<T>&);
void printall() {
for (int i = 0; i<cnt; i++)
cout << p[i] << ’\n’;
}
};
in the example, i is the local variable i declared in printall, cnt is the member cnt declared in Set, and
cout is the standard output stream declared in iostream. However, not every declaration can be found this
way; the resolution of some names must be postponed until the actual template-arguments are known. For
example, even though the name operator<< is known within the definition of printall() and a declaration
of it can be found in <iostream>, the actual declaration of operator<< needed to print p[i] cannot be
known until it is known what type T is (17.7.2).
— end example ]
10
If a name does not depend on a template-parameter (as defined in 17.7.2), a declaration (or set of declarations)
for that name shall be in scope at the point where the name appears in the template definition; the name is
bound to the declaration (or declarations) found at that point and this binding is not affected by declarations
that are visible at the point of instantiation. [ Example:
void f(char);
template<class T> void g(T t) {
f(1);
// f(char)
f(T(1));
// dependent
f(t);
// dependent
dd++;
// not dependent; error: declaration for dd not found
}
enum E { e };
void f(E);
double dd;
void h() {
g(e);
// will cause one call of f(char) followed by two calls of f(E)
g(’a’);
// will cause three calls of f(char)
}
— end example ]
11
[Note: For purposes of name lookup, default arguments and noexcept-specifiers of function templates and
default arguments and noexcept-specifier s of member functions of class templates are considered definitions
(17.6).
— end note ]
§ 17.7
344
17.7.1
Locally declared names
[temp.local]
1
Like normal (non-template) classes, class templates have an injected-class-name (Clause 12). The injected-
class-name can be used as a template-name or a type-name. When it is used with a template-argument-list, as
a template-argument for a template template-parameter, or as the final identifier in the elaborated-type-specifier
of a friend class template declaration, it refers to the class template itself. Otherwise, it is equivalent to the
template-name followed by the template-parameter s of the class template enclosed in <>.
2
Within the scope of a class template specialization or partial specialization, when the injected-class-name is
used as a type-name, it is equivalent to the template-name followed by the template-arguments of the class
template specialization or partial specialization enclosed in <>. [ Example:
template<template<class> class T> class A { };
template<class T> class Y;
template<> class Y<int> {
Y* p;
// meaning Y<int>
Y<char>* q;
// meaning Y<char>
A<Y>* a;
// meaning A<::Y>
class B {
template<class> friend class Y;
// meaning ::Y
};
};
— end example ]
3
The injected-class-name of a class template or class template specialization can be used either as a template-
name or a type-name wherever it is in scope. [ Example:
template <class T> struct Base {
Base* p;
};
template <class T> struct Derived: public Base<T> {
typename Derived::Base* p;
// meaning Derived::Base<T>
};
template<class T, template<class> class U = T::template Base> struct Third { };
Third<Base<int> > t;
// OK: default argument uses injected-class-name as a template
— end example ]
4
A lookup that finds an injected-class-name (13.2) can result in an ambiguity in certain cases (for example, if it
is found in more than one base class). If all of the injected-class-names that are found refer to specializations
of the same class template, and if the name is used as a template-name, the reference refers to the class
template itself and not a specialization thereof, and is not ambiguous. [ Example:
template <class T> struct Base { };
template <class T> struct Derived: Base<int>, Base<char> {
typename Derived::Base b;
// error: ambiguous
typename Derived::Base<double> d;
// OK
};
— end example ]
5
When the normal name of the template (i.e., the name from the enclosing scope, not the injected-class-name)
is used, it always refers to the class template itself and not a specialization of the template. [ Example:
template<class T> class X {
X* p;
// meaning X<T>
X<T>* p2;
X<int>* p3;
::X* p4;
// error: missing template argument list
// ::X does not refer to the injected-class-name
};
— end example ]
6
A template-parameter shall not be redeclared within its scope (including nested scopes). A template-parameter
shall not have the same name as the template name. [ Example:
§ 17.7.1
345
template<class T, int i> class Y {
int T;
// error: template-parameter redeclared
void f() {
char T;
// error: template-parameter redeclared
}
};
template<class X> class X;
// error: template-parameter redeclared
— end example ]
7
In the definition of a member of a class template that appears outside of the class template definition, the
name of a member of the class template hides the name of a template-parameter of any enclosing class
templates (but not a template-parameter of the member if the member is a class or function template).
[ Example:
template<class T> struct A {
struct B { /* ... */ };
typedef void C;
void f();
template<class U> void g(U);
};
template<class B> void A<B>::f() {
B b;
// A’s B, not the template parameter
}
template<class B> template<class C> void A<B>::g(C) {
B b;
// A’s B, not the template parameter
C c;
// the template parameter C, not A’s C
}
— end example ]
8
In the definition of a member of a class template that appears outside of the namespace containing the
class template definition, the name of a template-parameter hides the name of a member of this namespace.
[ Example:
namespace N {
class C { };
template<class T> class B {
void f(T);
};
}
template<class C> void N::B<C>::f(C) {
C b;
// C is the template parameter, not N::C
}
— end example ]
9
In the definition of a class template or in the definition of a member of such a template that appears outside
of the template definition, for each non-dependent base class (17.7.2.1), if the name of the base class or the
name of a member of the base class is the same as the name of a template-parameter, the base class name or
member name hides the template-parameter name (6.3.10). [ Example:
struct A {
struct B { /* ... */ };
int a;
int Y;
};
template<class B, class a> struct X : A {
B b;
// A’s B
a b;
// error: A’s a isn’t a type name
};
— end example ]
§ 17.7.1
346
17.7.2
Dependent names
[temp.dep]
1
Inside a template, some constructs have semantics which may differ from one instantiation to another. Such
a construct depends on the template parameters. In particular, types and expressions may depend on the
type and/or value of template parameters (as determined by the template arguments) and this determines
the context for name lookup for certain names. An expressions may be type-dependent (that is, its type
may depend on a template parameter) or value-dependent (that is, its value when evaluated as a constant
expression (8.6) may depend on a template parameter) as described in this subclause. In an expression of the
form:
postfix-expression ( expression-listopt )
where the postfix-expression is an unqualified-id, the unqualified-id denotes a dependent name if
(1.1)
any of the expressions in the expression-list is a pack expansion (17.6.3),
(1.2)
any of the expressions or braced-init-lists in the expression-list is type-dependent (17.7.2.2), or
(1.3)
the unqualified-id is a template-id in which any of the template arguments depends on a template
parameter.
If an operand of an operator is a type-dependent expression, the operator also denotes a dependent name.
Such names are unbound and are looked up at the point of the template instantiation (17.7.4.1) in both the
context of the template definition and the context of the point of instantiation.
2
[ Example:
template<class T> struct X : B<T> {
typename T::A* pa;
void f(B<T>* pb) {
static int i = B<T>::i;
pb->j++;
}
};
the base class name B<T>, the type name T::A, the names B<T>::i and pb->j explicitly depend on the
template-parameter.
— end example ]
3
In the definition of a class or class template, the scope of a dependent base class (17.7.2.1) is not examined
during unqualified name lookup either at the point of definition of the class template or member or during
an instantiation of the class template or member. [ Example:
typedef double A;
template<class T> class B {
typedef int A;
};
template<class T> struct X : B<T> {
A a;
// a has type double
};
The type name A in the definition of X<T> binds to the typedef name defined in the global namespace scope,
not to the typedef name defined in the base class B<T>.
— end example ] [ Example:
struct A {
struct B { /* ... */ };
int a;
int Y;
};
int a;
template<class T> struct Y : T {
struct B { /* ... */ };
B b;
// The B defined in Y
void f(int i) { a = i; }
// ::a
Y* p;
// Y<T>
};
Y<A> ya;
§ 17.7.2
347
The members A::B, A::a, and A::Y of the template argument A do not affect the binding of names in Y<A>.
— end example ]
17.7.2.1
Dependent types
[temp.dep.type]
1
A name refers to the current instantiation if it is
(1.1)
in the definition of a class template, a nested class of a class template, a member of a class template, or
a member of a nested class of a class template, the injected-class-name (Clause 12) of the class template
or nested class,
(1.2)
in the definition of a primary class template or a member of a primary class template, the name of the
class template followed by the template argument list of the primary template (as described below)
enclosed in <> (or an equivalent template alias specialization),
(1.3)
in the definition of a nested class of a class template, the name of the nested class referenced as a
member of the current instantiation, or
(1.4)
in the definition of a partial specialization or a member of a partial specialization, the name of the
class template followed by the template argument list of the partial specialization enclosed in <> (or an
equivalent template alias specialization). If the nth template parameter is a parameter pack, the nth
template argument is a pack expansion (17.6.3) whose pattern is the name of the parameter pack.
2
The template argument list of a primary template is a template argument list in which the nth template
argument has the value of the nth template parameter of the class template. If the nth template parameter
is a template parameter pack (17.6.3), the nth template argument is a pack expansion (17.6.3) whose pattern
is the name of the template parameter pack.
3
A template argument that is equivalent to a template parameter can be used in place of that template
parameter in a reference to the current instantiation. For a template type-parameter, a template argument
is equivalent to a template parameter if it denotes the same type. For a non-type template parameter, a
template argument is equivalent to a template parameter if it is an identifier that names a variable that is
equivalent to the template parameter. A variable is equivalent to a template parameter if
(3.1)
it has the same type as the template parameter (ignoring cv-qualification) and
(3.2)
its initializer consists of a single identifier that names the template parameter or, recursively, such a
variable.
[ Note: Using a parenthesized variable name breaks the equivalence.
— end note ]
[ Example:
template <class T> class A {
A* p1;
// A is the current instantiation
A<T>* p2;
// A<T> is the current instantiation
A<T*> p3;
// A<T*> is not the current instantiation
::A<T>* p4;
// ::A<T> is the current instantiation
class B {
B* p1;
// B is the current instantiation
A<T>::B* p2;
// A<T>::B is the current instantiation
typename A<T*>::B* p3;
// A<T*>::B is not the current instantiation
};
};
template <class T> class A<T*> {
A<T*>* p1;
// A<T*> is the current instantiation
A<T>* p2;
// A<T> is not the current instantiation
};
template <class T1, class T2, int I> struct B {
B<T1, T2, I>* b1;
// refers to the current instantiation
B<T2, T1, I>* b2;
// not the current instantiation
typedef T1 my_T1;
static const int my_I = I;
static const int my_I2 = I+0;
static const int my_I3 = my_I;
static const long my_I4 = I;
static const int my_I5 = (I);
B<my_T1, T2, my_I>* b3;
// refers to the current instantiation
§ 17.7.2.1
348
B<my_T1, T2, my_I2>* b4;
// not the current instantiation
B<my_T1, T2, my_I3>* b5;
// refers to the current instantiation
B<my_T1, T2, my_I4>* b6;
// not the current instantiation
B<my_T1, T2, my_I5>* b7;
// not the current instantiation
};
— end example ]
4
A dependent base class is a base class that is a dependent type and is not the current instantiation. [ Note: A
base class can be the current instantiation in the case of a nested class naming an enclosing class as a base.
[ Example:
template<class T> struct A {
typedef int M;
struct B {
typedef void M;
struct C;
};
};
template<class T> struct A<T>::B::C : A<T> {
M m;
// OK, A<T>::M
};
— end example ]
— end note ]
5
A name is a member of the current instantiation if it is
(5.1)
An unqualified name that, when looked up, refers to at least one member of a class that is the current
instantiation or a non-dependent base class thereof. [Note: This can only occur when looking up a
name in a scope enclosed by the definition of a class template.
— end note ]
(5.2)
A qualified-id in which the nested-name-specifier refers to the current instantiation and that, when
looked up, refers to at least one member of a class that is the current instantiation or a non-dependent
base class thereof. [ Note: If no such member is found, and the current instantiation has any dependent
base classes, then the qualified-id is a member of an unknown specialization; see below.
— end note ]
(5.3)
An id-expression denoting the member in a class member access expression (8.5.1.5) for which the type
of the object expression is the current instantiation, and the id-expression, when looked up (6.4.5),
refers to at least one member of a class that is the current instantiation or a non-dependent base class
thereof.
[Note: If no such member is found, and the current instantiation has any dependent base
classes, then the id-expression is a member of an unknown specialization; see below.
— end note ]
[ Example:
template <class T> class A {
static const int i = 5;
int n1[i];
// i refers to a member of the current instantiation
int n2[A::i];
// A::i refers to a member of the current instantiation
int n3[A<T>::i];
// A<T>::i refers to a member of the current instantiation
int f();
};
template <class T> int A<T>::f() {
return i;
// i refers to a member of the current instantiation
}
— end example ]
A name is a dependent member of the current instantiation if it is a member of the current instantiation that,
when looked up, refers to at least one member of a class that is the current instantiation.
6
A name is a member of an unknown specialization if it is
(6.1)
A qualified-id in which the nested-name-specifier names a dependent type that is not the current
instantiation.
(6.2)
A qualified-id in which the nested-name-specifier refers to the current instantiation, the current
instantiation has at least one dependent base class, and name lookup of the qualified-id does not find
any member of a class that is the current instantiation or a non-dependent base class thereof.
§ 17.7.2.1
349
(6.3)
An id-expression denoting the member in a class member access expression (8.5.1.5) in which either
(6.3.1)
the type of the object expression is the current instantiation, the current instantiation has at least
one dependent base class, and name lookup of the id-expression does not find a member of a class
that is the current instantiation or a non-dependent base class thereof; or
(6.3.2)
the type of the object expression is dependent and is not the current instantiation.
7
If a qualified-id in which the nested-name-specifier refers to the current instantiation is not a member of
the current instantiation or a member of an unknown specialization, the program is ill-formed even if the
template containing the qualified-id is not instantiated; no diagnostic required. Similarly, if the id-expression
in a class member access expression for which the type of the object expression is the current instantiation
does not refer to a member of the current instantiation or a member of an unknown specialization, the
program is ill-formed even if the template containing the member access expression is not instantiated; no
diagnostic required. [ Example:
template<class T> class A {
typedef int type;
void f() {
A<T>::type i;
// OK: refers to a member of the current instantiation
typename A<T>::other j;
// error: neither a member of the current instantiation nor
// a member of an unknown specialization
}
};
— end example ]
8
If, for a given set of template arguments, a specialization of a template is instantiated that refers to a member
of the current instantiation with a qualified-id or class member access expression, the name in the qualified-id
or class member access expression is looked up in the template instantiation context. If the result of this
lookup differs from the result of name lookup in the template definition context, name lookup is ambiguous.
[ Example:
struct A {
int m;
};
struct B {
int m;
};
template<typename T>
struct C : A, T {
int f() { return this->m; }
// finds A::m in the template definition context
int g() { return m; }
// finds A::m in the template definition context
};
template int C<B>::f();
// error: finds both A::m and B::m
template int C<B>::g();
// OK: transformation to class member access syntax
// does not occur in the template definition context; see 12.2.2
— end example ]
9
A type is dependent if it is
(9.1)
a template parameter,
(9.2)
a member of an unknown specialization,
(9.3)
a nested class or enumeration that is a dependent member of the current instantiation,
(9.4)
a cv-qualified type where the cv-unqualified type is dependent,
(9.5)
a compound type constructed from any dependent type,
(9.6)
an array type whose element type is dependent or whose bound (if any) is value-dependent,
(9.7)
a function type whose exception specification is value-dependent,
(9.8)
a simple-template-id in which either the template name is a template parameter or any of the template
arguments is a dependent type or an expression that is type-dependent or value-dependent or is a pack
§ 17.7.2.1
350
expansion [ Note: This includes an injected-class-name (Clause 12) of a class template used without a
template-argument-list.
— end note ] , or
(9.9)
denoted by decltype(expression), where expression is type-dependent (17.7.2.2).
10
[Note: Because typedefs do not introduce new types, but instead simply refer to other types, a name that
refers to a typedef that is a member of the current instantiation is dependent only if the type referred to is
dependent.
— end note ]
17.7.2.2
Type-dependent expressions
[temp.dep.expr]
1
Except as described below, an expression is type-dependent if any subexpression is type-dependent.
2
this is type-dependent if the class type of the enclosing member function is dependent (17.7.2.1).
3
An id-expression is type-dependent if it contains
(3.1)
an identifier associated by name lookup with one or more declarations declared with a dependent type,
(3.2)
an identifier associated by name lookup with a non-type template-parameter declared with a type that
contains a placeholder type (10.1.7.4),
(3.3)
an identifier associated by name lookup with one or more declarations of member functions of the
current instantiation declared with a return type that contains a placeholder type,
(3.4)
an identifier associated by name lookup with a structured binding declaration (11.5) whose brace-or-
equal-initializer is type-dependent,
(3.5)
the identifier __func__ (11.4.1), where any enclosing function is a template, a member of a class
template, or a generic lambda,
(3.6)
a template-id that is dependent,
(3.7)
a conversion-function-id that specifies a dependent type, or
(3.8)
a nested-name-specifier or a qualified-id that names a member of an unknown specialization;
or if it names a dependent member of the current instantiation that is a static data member of type “array of
unknown bound of T” for some T (17.6.1.3). Expressions of the following forms are type-dependent only if
the type specified by the type-id, simple-type-specifier or new-type-id is dependent, even if any subexpression
is type-dependent:
simple-type-specifier ( expression-listopt )
::opt new new-placementopt new-type-id new-initializeropt
::opt new new-placementopt ( type-id ) new-initializeropt
dynamic_cast < type-id > ( expression )
static_cast < type-id > ( expression )
const_cast < type-id > ( expression )
reinterpret_cast < type-id > ( expression )
( type-id ) cast-expression
4
Expressions of the following forms are never type-dependent (because the type of the expression cannot be
dependent):
literal
postfix-expression . pseudo-destructor-name
postfix-expression -> pseudo-destructor-name
sizeof unary-expression
sizeof ( type-id )
sizeof ... ( identifier )
alignof ( type-id )
typeid ( expression )
typeid ( type-id )
::opt delete cast-expression
::opt delete [ ] cast-expression
throw assignment-expressionopt
noexcept ( expression )
[ Note: For the standard library macro offsetof, see 21.2. — end note ]
5
A class member access expression (8.5.1.5) is type-dependent if the expression refers to a member of the
current instantiation and the type of the referenced member is dependent, or the class member access
expression refers to a member of an unknown specialization. [Note: In an expression of the form x.y or
§ 17.7.2.2
351

 

 

 

 

 

 

 

Content      ..     10      11      12      13     ..