A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from http://en.cppreference.com/w/cpp/language/template_arguments.html below:

Template arguments - cppreference.com

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

Each parameter in template-parameter-list (see template identifier syntax) belongs to one of the following categories:

[edit] Constant template arguments

Also known as non-type template arguments (see below).

Given the type of the constant template parameter declaration as T and the template argument provided for the parameter as E.

The invented declaration T x = E; must satisfy the semantic constraints for the definition of a constexpr variable with static storage duration.

(since C++20)

If T contains a placeholder type, or is a placeholder for a deduced class type, the type of the template parameter is the type deduced for the variable x in the invented declaration T x = E;.

If a deduced parameter type is not a structural 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 int
B<'a'> b2; // OK: constant template parameter type is char
B<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 site
template<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 parameter P of (possibly deduced)(since C++17) type T is determined from its template argument A as follows:

(until C++11)
(since C++11)
(until C++20)
  • The lifetime of v ends immediately after initializing it and P.
  • If the initialization of P satisfies any of the following conditions, the program is ill-formed:
(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:

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 type and 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

(since C++17)
template<const int* 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, const char* 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;
    static int s;
} s;
 
X<&a[2]> x3; // error (until C++20): address of array element
X<&s.m> x4;  // error (until C++20): address of non-static member
X<&s.s> x5;  // OK: address of static member
X<&S::s> x6; // OK: address of static member
 
template<const int& CRI>
struct B {};
 
B<1> b2;     // error: temporary would be required for template argument
int c = 1;
B<c> b1;     // OK
[edit] Type template arguments

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

template<typename T>
class X {}; // class template
 
struct A;            // incomplete type
typedef struct {} 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 an id-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 template
class A { int x; };
 
template<typename T> // partial specialization
class A<T*> { long x; };
 
// class template with a template template parameter V
template<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 argument A to a template template parameter P, P must be at least as specialized as A (see below). If P's parameter list includes a parameter pack, zero or more template parameters (or parameter packs) from A's template parameter list are matched by it.(since C++11)

Formally, a template template-parameter P is at least as specialized as a template template argument A if, given the following rewrite to two function templates, the function template corresponding to P is at least as specialized as the function template corresponding to A according to the partial ordering rules for function templates. Given an invented class template X with the template parameter list of A (including default arguments):

If the rewrite produces an invalid type, then P is not at least as specialized as A.

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 eval
eval<B<int, float>> eB; // OK: matches partial specialization of eval
eval<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 type
eval<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 type
eval<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 of P0522R0, each of the template parameters of A must match corresponding template parameters of P 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:

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; // OK
X<B> xb; // OK after P0522R0
         // Error earlier: not an exact match
X<C> xc; // OK after P0522R0
         // Error earlier: not an exact match
 
template<template<class...> class Q> class Y { /* ... */ };
Y<A> ya; // OK
Y<B> yb; // OK
Y<C> yc; // OK
 
template<auto n> class D { /* ... */ };   // note: C++17
template<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++17
FA<SI>(); // Error
[edit] Template argument equivalence

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

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

(since C++20) [edit] Ambiguity resolution

If a template argument can be interpreted as both a type-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 by P2841R6 / PR #7587.

[edit] Example [edit] Defect reports

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

DR Applied to Behavior as published Correct behavior CWG 150
(P0522R0) C++98 template-template arguments had to match parameter
lists of template-template parameters exactly more specialized
also allowed CWG 354 C++98 null pointer values could not be constant template arguments allowed CWG 1398 C++11 constant template arguments could not have type std::nullptr_t allowed CWG 1570 C++98 constant template arguments could designate addresses of subobjects not allowed P2308R1 C++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

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4