Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Template arguments

      From cppreference.com
      <cpp‎ |language
       
       
      C++ language
      General topics
      Flow control
      Conditional execution statements
      Iteration statements (loops)
      Jump statements
      Functions
      Function declaration
      Lambda function expression
      inline specifier
      Dynamic exception specifications(until C++17*)
      noexcept specifier(C++11)
      Exceptions
      Namespaces
      Types
      Specifiers
      constexpr(C++11)
      consteval(C++20)
      constinit(C++20)
      Storage duration specifiers
      Initialization
      Expressions
      Alternative representations
      Literals
      Boolean -Integer -Floating-point
      Character -String -nullptr(C++11)
      User-defined(C++11)
      Utilities
      Attributes(C++11)
      Types
      typedef declaration
      Type alias declaration(C++11)
      Casts
      Memory allocation
      Classes
      Class-specific function properties
      Special member functions
      Templates
      Miscellaneous
       
       

      In order for a template to be instantiated, everytemplate parameter must be replaced by a corresponding template argument. The arguments are either explicitly provided, deduced or defaulted.

      Each parameter intemplate-parameter-list (seetemplate identifier syntax) belongs to one of the following categories:

      • constant template argument
      • type template argument
      • template template argument

      Contents

      [edit]Constant template arguments

      Also known asnon-type template arguments (seebelow).

      The template argument that can be used with a constant template parameter can be anymanifestly constant-evaluated expression.

      (until C++11)

      The template argument that can be used with a constant template parameter can be anyinitializer clause. If the initializer clause is an expression, it must bemanifestly constant-evaluated.

      (since C++11)

      Given thetype of theconstant template parameter declaration asT and the template argument provided for the parameter asE.

      The invented declarationT x= E; must satisfy the semantic constraints for the definition of aconstexpr variable withstatic storage duration.

      (since C++20)

      IfT contains aplaceholder type, or is aplaceholder for a deduced class type, the type of the template parameter is the type deduced for the variablex in the invented declarationT x= E;.

      If a deduced parameter type is not astructural type, the program is ill-formed.

      For constant template parameter packs whose type uses a placeholder type, the type is independently deduced for each template argument and need not match.

      (since C++17)
      template<auto n>struct B{/* ... */}; B<5> b1;// OK: constant template parameter type is intB<'a'> b2;// OK: constant template parameter type is charB<2.5> b3;// error (until C++20): constant template parameter type cannot be double // C++20 deduced class type placeholder, class template arguments are deduced at the// call sitetemplate<std::array arr>void f(); f<std::array<double,8>{}>(); template<auto...>struct C{}; C<'C',0,2L, nullptr> x;// OK

      The value of a constant template parameterP of (possibly deduced)(since C++17) typeT is determined from its template argumentA as follows:

      (until C++11)
      • IfA is an expression:
      • Otherwise (A is a braced-enclosed initializer list), a temporary variableconstexpr T v= A; is introduced. The value ofP is that ofv.
      • Thelifetime ofv ends immediately after initializing it.
      (since C++11)
      (until C++20)
      • IfT is not a class type andA is an expression:
      • Otherwise (T is a class type orA is a braced-enclosed initializer list), a temporary variableconstexpr T v= A; is introduced.
      • Thelifetime ofv ends immediately after initializing it andP.
      • If the initialization ofP satisfies any of the following conditions, the program is ill-formed:
      • Otherwise, the value ofP is that ofv.
      (since C++20)
      template<int i>struct C{/* ... */}; C<{42}> c1;// OK template<auto n>struct B{/* ... */}; struct J1{    J1* self= this;}; B<J1{}> j1;// error: initialization of the template parameter object//        is not a constant expression struct J2{    J2*self= this;constexpr J2(){}constexpr J2(const J2&){}}; B<J2{}> j2;// error: the template parameter object is not//        template-argument-equivalent to introduced temporary

      The following limitations apply when instantiating templates that have constant template parameters:

      • For integral and arithmetic types, the template argument provided during instantiation must be aconverted constant expression of the template parameter's type (so certain implicit conversion applies).
      • For pointers to objects, the template arguments have to designate the address of a complete object with staticstorage duration and alinkage (either internal or external), or a constant expression that evaluates to the appropriate null pointer orstd::nullptr_t(since C++11) value.
      • For pointers to functions, the valid arguments are pointers to functions with linkage (or constant expressions that evaluate to null pointer values).
      • For lvalue reference parameters, the argument provided at instantiation cannot be a temporary, an unnamed lvalue, or a named lvalue with no linkage (in other words, the argument must have linkage).
      • For pointers to members, the argument has to be a pointer to member expressed as&Class::Member or a constant expression that evaluates to null pointer orstd::nullptr_t(since C++11) value.

      In particular, this implies that string literals, addresses of array elements, and addresses of non-static members cannot be used as template arguments to instantiate templates whose corresponding constant template parameters are pointers to objects.

      (until C++17)

      constant template parameters of reference or pointer typeand non-static data members of reference or pointer type in a constant template parameter of class type and its subobjects(since C++20) cannot refer to/be the address of

      • a temporary object (including one created duringreference initialization);
      • astring literal;
      • the result oftypeid;
      • the predefined variable__func__;
      • or a subobject (including non-static class member, base subobject, or array element) of one of the above(since C++20).
      (since C++17)
      template<constint* pci>struct X{}; int ai[10];X<ai> xi;// OK: array to pointer conversion and cv-qualification conversion struct Y{}; template<const Y& b>struct Z{}; Y y;Z<y> z;// OK: no conversion template<int(&pa)[5]>struct W{}; int b[5];W<b> w;// OK: no conversion void f(char);void f(int); template<void(*pf)(int)>struct A{}; A<&f> a;// OK: overload resolution selects f(int)
      template<class T,constchar* p>class X{}; X<int,"Studebaker"> x1;// error: string literal as template-argument template<int* p>class X{}; int a[10]; struct S{int m;staticint s;} s; X<&a[2]> x3;// error (until C++20): address of array elementX<&s.m> x4;// error (until C++20): address of non-static memberX<&s.s> x5;// OK: address of static memberX<&S::s> x6;// OK: address of static member template<constint& CRI>struct B{}; B<1> b2;// error: temporary would be required for template argumentint c=1;B<c> b1;// OK

      [edit]Type template arguments

      A template argument for a type template parameter must be atype-id, which may name an incomplete type:

      template<typename T>class X{};// class template struct A;// incomplete typetypedefstruct{} B;// type alias to an unnamed type int main(){    X<A> x1;// OK: 'A' names a type    X<A*> x2;// OK: 'A*' names a type    X<B> x3;// OK: 'B' names a type}

      [edit]Template template arguments

      A template argument for a template template parameter must be anid-expression which names a class template or a template alias.

      When the argument is a class template, only the primary template is considered when matching the parameter. The partial specializations, if any, are only considered when a specialization based on this template template parameter happens to be instantiated.

      template<typename T>// primary templateclass A{int x;}; template<typename T>// partial specializationclass A<T*>{long x;}; // class template with a template template parameter Vtemplate<template<typename>class V>class C{    V<int> y;// uses the primary template    V<int*> z;// uses the partial specialization}; C<A> c;// c.y.x has type int, c.z.x has type long

      To match a template template argumentA to a template template parameterP,P must beat least as specialized asA (see below). IfP's parameter list includes aparameter pack, zero or more template parameters (or parameter packs) fromA's template parameter list are matched by it.(since C++11)

      Formally, a template template-parameterP isat least as specialized as a template template argumentA if, given the following rewrite to two function templates, the function template corresponding toP is at least as specialized as the function template corresponding toA according to the partial ordering rules forfunction templates. Given an invented class templateX with the template parameter list ofA (including default arguments):

      • Each of the two function templates has the same template parameters, respectively, asP orA.
      • Each function template has a single function parameter whose type is a specialization ofX with template arguments corresponding to the template parameters from the respective function template where, for each template parameterPP in the template parameter list of the function template, a corresponding template argumentAA is formed. IfPP declares a parameter pack, thenAA is the pack expansionPP...; otherwise,(since C++11)AA is the id-expressionPP.

      If the rewrite produces an invalid type, thenP is not at least as specialized asA.

      template<typename T>struct eval;// primary template template<template<typename,typename...>class TT,typename T1,typename...Rest>struct eval<TT<T1, Rest...>>{};// partial specialization of eval template<typename T1>struct A;template<typename T1,typename T2>struct B;template<int N>struct C;template<typename T1,int N>struct D;template<typename T1,typename T2,int N=17>struct E; eval<A<int>> eA;// OK: matches partial specialization of evaleval<B<int,float>> eB;// OK: matches partial specialization of evaleval<C<17>> eC;// error: C does not match TT in partial specialization// because TT's first parameter is a// type template parameter, while 17 does not name a typeeval<D<int,17>> eD;// error: D does not match TT in partial specialization// because TT's second parameter is a// type parameter pack, while 17 does not name a typeeval<E<int,float>> eE;// error: E does not match TT in partial specialization// because E's third (default) parameter is a constant

      Before the adoption ofP0522R0, each of the template parameters ofA must match corresponding template parameters ofP exactly. This hinders many reasonable template argument from being accepted.

      Although it was pointed out very early (CWG#150), by the time it was resolved, the changes were applied to the C++17 working paper and the resolution became a de facto C++17 feature. Many compilers disable it by default:

      • GCC disables it in all language modes prior to C++17 by default, it can only be enabled by setting a compiler flag in these modes.
      • Clang disables it in all language modes by default, it can only be enabled by setting a compiler flag.
      • Microsoft Visual Studio treats it as a normal C++17 feature and only enables it in C++17 and later language modes (i.e. no support in C++14 language mode, which is the default mode).
      template<class T>class A{/* ... */};template<class T,class U= T>class B{/* ... */};template<class...Types>class C{/* ... */}; template<template<class>class P>class X{/* ... */};X<A> xa;// OKX<B> xb;// OK after P0522R0// Error earlier: not an exact matchX<C> xc;// OK after P0522R0// Error earlier: not an exact match template<template<class...>class Q>class Y{/* ... */};Y<A> ya;// OKY<B> yb;// OKY<C> yc;// OK template<auto n>class D{/* ... */};// note: C++17template<template<int>class R>class Z{/* ... */};Z<D> zd;// OK after P0522R0: the template parameter// is more specialized than the template argument template<int>struct SI{/* ... */};template<template<auto>class>void FA();// note: C++17FA<SI>();// Error

      [edit]Template argument equivalence

      Template argument equivalence is used to determine whether twotemplate identifiers are same.

      Two values aretemplate-argument-equivalent if they are of the same type and any of the following conditions is satisfied:

      • They are of integral or enumeration type and their values are the same.
      • They are of pointer type and they have the same pointer value.
      • They are of pointer-to-member type and they refer to the same class member or are both the null member pointer value.
      • They are of lvalue reference type and they refer to the same object or function.
      (since C++11)
      • They are of floating-point type and their values are identical.
      • They are of array type (in which case the arrays must be member objects of some class/union) and their corresponding elements are template-argument-equivalent.
      • They are of union type and either they both have no active member or they have the same active member and their active members are template-argument-equivalent.
      • They are of a lambda closure type.
      • They are of non-union class type and their corresponding direct subobjects and reference members are template-argument-equivalent.
      (since C++20)

      [edit]Ambiguity resolution

      If a template argument can be interpreted as both atype-id and an expression, it is always interpreted as a type-id, even if the corresponding template parameter is constant:

      template<class T>void f();// #1 template<int I>void f();// #2 void g(){    f<int()>();// “int()” is both a type and an expression,// calls #1 because it is interpreted as a type}

      [edit]Notes

      Before C++26, constant template argument were called non-type template argument in the standard wording. The terminology was changed byP2841R6 /PR #7587.

      Feature-test macroValueStdFeature
      __cpp_template_template_args201611L(C++17)
      (DR)
      Matching oftemplate template arguments
      __cpp_nontype_template_args201411L(C++17)Allow constant evaluation for allconstant template arguments
      201911L(C++20)Class types and floating-point types inconstant template parameters

      [edit]Example

      This section is incomplete
      Reason: no example

      [edit]Defect reports

      The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

      DRApplied toBehavior as publishedCorrect behavior
      CWG 150
      (P0522R0)
      C++98template-template arguments had to match parameter
      lists of template-template parameters exactly
      more specialized
      also allowed
      CWG 354C++98null pointer values could not be constant template argumentsallowed
      CWG 1398C++11constant template arguments could not have typestd::nullptr_tallowed
      CWG 1570C++98constant template arguments could designate addresses of subobjectsnot allowed
      P2308R1C++11
      C++20
      1. list-initialization was not allowed for
          constant template arguments (C++11)
      2. it was unclear how constant template
          parameters of class types are initialized (C++20)
      1. allowed
      2. made clear
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/template_arguments&oldid=182884"

      [8]ページ先頭

      ©2009-2025 Movatter.jp