Files
cppdraft_translate/cppdraft/temp/param.md
2025-10-25 03:02:53 +03:00

26 KiB
Raw Blame History

[temp.param]

13 Templates [temp]

13.2 Template parameters [temp.param]

1

#

The syntax fortemplate-parameters is:

template-parameter:
type-parameter
parameter-declaration
type-tt-parameter
variable-tt-parameter
concept-tt-parameter

type-parameter:
type-parameter-key ...opt identifieropt
type-parameter-key identifieropt = type-id
type-constraint ...opt identifieropt
type-constraint identifieropt = type-id

type-parameter-key:
class
typename

type-constraint:
nested-name-specifieropt concept-name
nested-name-specifieropt concept-name < template-argument-listopt >

type-tt-parameter:
template-head type-parameter-key ...opt identifieropt
template-head type-parameter-key identifieropt type-tt-parameter-default

type-tt-parameter-default:
= nested-name-specifieropt template-name
= nested-name-specifier template template-name

variable-tt-parameter:
template-head auto ...opt identifieropt
template-head auto identifieropt = nested-name-specifieropt template-name

concept-tt-parameter:
template < template-parameter-list > concept ...opt identifieropt
template < template-parameter-list > concept identifieropt = nested-name-specifieropt template-name

The component names of a type-constraint are its concept-name and those of its nested-name-specifier (if any).

[Note 1:

The > token following thetemplate-parameter-list of atype-tt-parameter,variable-tt-parameter, orconcept-tt-parameter can be the product of replacing a>> token by two consecutive > tokens ([temp.names]).

— end note]

2

#

A template parameter is of one of the following kinds:

3

#

Type template template parameters, variable template template parameters, and concept template parameters are collectively referred to as template template parameters.

4

#

The nested-name-specifier of a type-constraint, if any, shall not be dependent.

5

#

A concept template parameter shall not have associated constraints ([temp.constr.decl]).

6

#

If a template-parameter is a parameter-declaration that declares a pack ([dcl.fct]), or otherwise has an ellipsis prior to its optional identifier, then the template-parameter declares a template parameter pack ([temp.variadic]).

A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded packs is a pack expansion.

Similarly, a template parameter pack that is a template template parameter with atemplate-parameter-list containing one or more unexpanded packs is a pack expansion.

A type parameter pack with a type-constraint that contains an unexpanded parameter pack is a pack expansion.

A template parameter pack that is a pack expansion shall not expand a template parameter pack declared in the sametemplate-parameter-list.

[Example 1: template <class... Types> // Types is a template type parameter packclass Tuple; // but not a pack expansiontemplate <class T, int... Dims> // Dims is a constant template parameter packstruct multi_array; // but not a pack expansiontemplate <class... T>struct value_holder {template <T... Values> struct apply { }; // Values is a constant template parameter pack}; // and a pack expansiontemplate <class... T, T... Values> // error: Values expands template type parameterstruct static_array; // pack T within the same template parameter list — end example]

7

#

There is no semantic difference betweenclass andtypename in atype-parameter-key.

typename followed by anunqualified-id names a template type parameter.

typename followed by aqualified-id denotes the type in aparameter-declaration.

A template-parameter of the formclass identifier is a type-parameter.

[Example 2: class T { /* ... */ };int i;

template<class T, T i> void f(T t) { T t1 = i; // template parameters T and i::T t2 = ::i; // global namespace members T and i}

Here, the template f has a type template parameter called T, rather than an unnamed constant template parameter of class T.

— end example]

The parameter-declaration of a template-parameter shall not have a storage-class-specifier.

Types shall not be defined in a template parameter declaration.

8

#

The identifier in a template-parameter denoting a type or template is not looked up.

An identifier that does not follow an ellipsis is defined to be

a typedef-name for a type-parameter,

a template-name for a variable-tt-parameter,

a template-name for a type-tt-parameter, or

a concept-name for a concept-tt-parameter,

in the scope of the template declaration.

9

#

A type-constraint Q that designates a concept C can be used to constrain a contextually-determined type or template type parameter pack T with a constraint-expression E defined as follows.

If Q is of the form C<A1, …, An>, then let E′ be C<T, A1, …, An>.

Otherwise, let E′ be C.

If T is not a pack, then E is E′, otherwise E is (E′ && ...).

This constraint-expression E is called theimmediately-declared constraint of Q for T.

The concept designated by a type-constraint shall be a type concept ([temp.concept]).

10

#

A type-parameter that starts with a type-constraint introduces the immediately-declared constraint of the type-constraint for the parameter.

[Example 3: template concept C1 = true;template<typename... Ts> concept C2 = true;template<typename T, typename U> concept C3 = true;

template struct s1; // associates C1template<C1... T> struct s2; // associates (C1 && ...)template<C2... T> struct s3; // associates (C2 && ...)template<C3 T> struct s4; // associates C3<T, int>template<C3... T> struct s5; // associates (C3<T, int> && ...) — end example]

11

#

A constant template parameter shall have one of the following (possibly cv-qualified) types:

a structural type (see below),

a type that contains a placeholder type ([dcl.spec.auto]), or

a placeholder for a deduced class type ([dcl.type.class.deduct]).

The top-levelcv-qualifiers on thetemplate-parameter are ignored when determining its type.

12

#

A structural type is one of the following:

a scalar type, or

an lvalue reference type, or

a literal class type with the following properties:

all base classes and non-static data members are public and non-mutable and

the types of all base classes and non-static data members are structural types or (possibly multidimensional) arrays thereof.

13

#

An id-expression naming a constant template parameter of class type T denotes a static storage duration object of type const T, known as a template parameter object, which is template-argument-equivalent ([temp.type]) to the corresponding template argument after it has been converted to the type of the template parameter ([temp.arg.nontype]).

No two template parameter objects are template-argument-equivalent.

[Note 2:

If an id-expression names a non-reference constant template parameter, then it is a prvalue if it has non-class type.

Otherwise, if it is of class type T, it is an lvalue and has type const T ([expr.prim.id.unqual]).

— end note]

[Example 4: using X = int;struct A {};template<const X& x, int i, A a> void f() { i++; // error: change of template parameter value&x; // OK&i; // error: address of non-reference template parameter&a; // OKint& ri = i; // error: attempt to bind non-const reference to temporaryconst int& cri = i; // OK, const reference binds to temporaryconst A& ra = a; // OK, const reference binds to a template parameter object} — end example]

14

#

[Note 3:

A constant template parameter cannot be declared to have type cv void.

[Example 5: template class X; // errortemplate<void* pv> class Y; // OK — end example]

— end note]

15

#

A constant template parameterof type “array of T” orof function type T is adjusted to be of type “pointer to T”.

[Example 6: template<int* a> struct R { /* ... / };template<int b[5]> struct S { / ... */ };int p; R<&p> w; // OK S<&p> x; // OK due to parameter adjustmentint v[5]; R y; // OK due to implicit argument conversion S z; // OK due to both adjustment and conversion — end example]

16

#

A constant template parameter declared with a type that contains a placeholder type with a type-constraint introduces the immediately-declared constraint of the type-constraint for the invented type corresponding to the placeholder ([dcl.fct]).

17

#

A default template argument is a template argument ([temp.arg]) specified after = in a template-parameter.

A default template argument may be specified for any kind of template parameter that is not a template parameter pack ([temp.variadic]).

A default template argument may be specified in a template declaration.

A default template argument shall not be specified in the template-parameter-lists of the definition of a member of a class template that appears outside of the member's class.

A default template argument shall not be specified in a friend class template declaration.

If a friend function template declaration D specifies a default template argument, that declaration shall be a definition and there shall be no other declaration of the function template which is reachable from D or from which D is reachable.

18

#

The set of default template arguments available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are ([dcl.fct.default]).

[Example 7:

template<class T1, class T2 = int> class A;template class A; is equivalent totemplate class A;

— end example]

19

#

If a template-parameter of a class template, variable template, or alias template has a default template argument, each subsequent template-parameter shall either have a default template argument supplied or declare a template parameter pack.

If a template-parameter of a primary class template, primary variable template, or alias template declares a template parameter pack, it shall be the last template-parameter.

If a template-parameter of a function template declares a template parameter pack, it shall not be followed by another template-parameter unless that template parameter is deducible from the parameter-type-list ([dcl.fct]) of the function template or has a default argument ([temp.deduct]).

A template parameter of a deduction guide template ([temp.deduct.guide]) that does not have a default argument shall be deducible from the parameter-type-list of the deduction guide template.

[Example 8: template class B; // error// U can be neither deduced from the parameter-type-list nor specifiedtemplate<class... T, class... U> void f() { } // errortemplate<class... T, class U> void g() { } // error — end example]

20

#

When parsing a default template argument for a constant template parameter, the first non-nested > is taken as the end of the template-parameter-list rather than a greater-than operator.

[Example 9: template 4 > // syntax errorclass X { /* ... */ };

template 4) > // OKclass Y { /* ... */ }; — end example]

21

#

A template-parameter of a template template-parameter is permitted to have a default template argument.

When such default arguments are specified, they apply to the template template-parameter in the scope of the template template-parameter.

[Example 10: template <template class T> struct A {inline void f(); inline void g();};template <template class T> void A::f() { T<> t; // error: TT has no default template argument}template <template class T> void A::g() { T<> t; // OK, T} — end example]

The associated constraints of a template template parameter shall not contain a concept-dependent constraint ([temp.constr.concept]).

[Example 11: template<template concept C, template class TT // error: C forms a concept-dependent constraint>struct A {}; — end example]