Chapter 12

Fundamentals in Depth

In this chapter we review some of the fundamentals introduced in the first part of this book in depth: the declaration of templates, the restrictions on template parameters, the constraints on template arguments, and so forth.

12.1 Parameterized Declarations

C++ currently supports four fundamental kinds of templates: class templates, function templates, variable templates, and alias templates. Each of these template kinds can appear in namespace scope, but also in class scope. In class scope they become nested class templates, member function templates, static data member templates, and member alias templates. Such templates are declared much like ordinary classes, functions, variables, and type aliases (or their class member counterparts) except for being introduced by a parameterization clause of the form

template<parameters here>

Note that C++17 introduced another construct that is introduced with such a parameterization clause: deduction guides (see Section 2.9 on page 42 and Section 15.12.1 on page 314). Those aren’t called templates in this book (e.g., they are not instantiated), but the syntax was chosen to be reminiscent of function templates.

We’ll come back to the actual template parameter declarations in a later section. First, some examples illustrate the four kinds of templates. They can occur in namespace scope (globally or in a namespace) as follows:

details/definitions1.hpp

template<typename T>            // a namespace scope class template
class Data {
  public:
    static constexpr bool copyable = true;
    …
};
template<typename T>            // a namespace scope function template
void log (T x) {
   …
}

template<typename T>           // a namespace scope variable template (since C++14)
T zero = 0;

template<typename T>           // a namespace scope variable template (since C++14)
bool dataCopyable = Data<T>::copyable;

template<typename T>           // a namespace scope alias template
using DataList = Data<T*>;

Note that in this example, the static data member Data<T>::copyable is not a variable template, even though it is indirectly parameterized through the parameterization of the class template Data. However, a variable template can appear in class scope (as the next example will illustrate), and in that case it is a static data member template.

The following example shows the four kinds of templates as class members that are defined within their parent class:

details/definitions2.hpp

class Collection {
  public:
    template<typename T>        // an in-class member class template definition
    class Node {
        …
    };

    template<typename T>        // an in-class (and therefore implicitly inline)
    T* alloc() {                //member function template definition
        …
    }

    template<typename T>        // a member variable template (since C++14)
     static T zero = 0;
    template<typename T>        // a member alias template
     using NodePtr = Node<T>*;
};

Note that in C++17, variables—including static data members—and variable templates can be “in-line,” which means that their definition can be repeated across translation units. This is redundant for variable templates, which can always be defined in multiple translation units. Unlike member functions, however, a static data member being defined in its enclosing class does not make it inline: The keyword inline must be specified in all cases.

Finally, the following code demonstrates how member templates that are not alias templates can be defined out-of-class:

details/definitions3.hpp

template<typename T>            // a namespace scope class template
class List {
  public:
    List() = default;           // because a template constructor is defined

    template<typename U>        // another member class template,
     class Handle;              // without its definition

    template<typename U>        // a member function template
     List (List<U> const&);     // (constructor)

    template<typename U>        // a member variable template (since C++14)
     static U zero;
};

template<typename T>            // out-of-class member class template definition
 template<typename U>
class List<T>::Handle {
    …
};

template<typename T>            // out-of-class member function template definition
 template<typename T2>
List<T>::List (List<T2> const& b)
{
   …
}

template<typename T>           // out-of-class static data member template definition
 template<typename U>
U List<T>::zero = 0;

Member templates defined outside their enclosing class may need multiple template<> parameterization clauses: one for every enclosing class template and one for the member template itself. The clauses are listed starting from the outermost class template.

Note also that a constructor template (a special kind of member function template) disables the implicit declaration of the default constructor (because it is only implicitly declared if no other constructor is declared). Adding a defaulted declaration

List() = default;

ensures an instance of List<T> is default-constructible with the semantics of an implicitly declared constructor.

Union Templates

Union templates are possible too (and they are considered a kind of class template):

template<typename T>
union AllocChunk {
    T object;
    unsigned char bytes[sizeof(T)];
};

Default Call Arguments

Function templates can have default call arguments just like ordinary function declarations:

    template<typename T>
    void report_top (Stack<T> const&, int number = 10);

    template<typename T>
    void fill (Array<T>&, T const& = T{});  // T{} is zero for built-in types

The latter declaration shows that a default call argument could depend on a template parameter. It also can be defined as (the only way possible before C++11, see Section 5.2 on page 68)

    template<typename T>
    void fill (Array<T>&, T const& = T());  // T() is zero for built-in types

When the fill() function is called, the default argument is not instantiated if a second function call argument is supplied. This ensures that no error is issued if the default call argument cannot be instantiated for a particular T. For example:

class Value {
  public:
    explicit Value(int);  // no default constructor
};

void init (Array<Value>& array)
{
    Value zero(0);

    fill(array, zero);   // OK: default constructor not used
    fill(array);         // ERROR: undefined default constructor for Value is used
}

Nontemplate Members of Class Templates

In addition to the four fundamental kinds of templates declared inside a class, you can also have ordinary class members parameterized by being part of a class template They are occasionally (erroneously) also referred to as member templates. Although they can be parameterized, such definitions aren’t quite first-class templates. Their parameters are entirely determined by the template of which they are members. For example:

template<int I>
class CupBoard
{
    class Shelf;                // ordinary class in class template
    void open();                // ordinary function in class template
    enum Wood : unsigned char;  // ordinary enumeration type in class template
    static double totalWeight;  // ordinary static data member in class template
};

The corresponding definitions only specify a parameterization clause for the parent class templates, but not for the member itself, because it is not a template (i.e., no parameterization clause is associated with the name appearing after the last ::):

template<int I>         // definition of ordinary class in class template
class CupBoard<I>::Shelf {
    …
};

template<int I>         // definition of ordinary function in class template
void CupBoard<I>::open()
{
    …
}

template<int I>         // definition of ordinary enumeration type class in class template
enum CupBoard<I>::Wood {
    Maple, Cherry, Oak
};

template<int I>         // definition of ordinary static member in class template
double CupBoard<I>::totalWeight = 0.0;

Since C++17, the static totalWeight member can be initialized inside the class template using inline:

template<int I>
class CupBoard
    …
    inline static double totalWeight = 0.0;
};

Although such parameterized definitions are commonly called templates, the term doesn’t quite apply to them. A term that has been occasionally suggested for these entities is temploid. Since C++17, the C++ standard does define the notion of a templated entity, which includes templates and temploids as well as, recursively, any entity defined or created in templated entities (that includes, e.g., a friend function defined inside a class template (see Section 2.4 on page 30) or the closure type of a lambda expression appearing in a template). Neither temploid nor templated entity has gained much traction so far, but they may be useful terms to communicate more precisely about C++ templates in the future.

12.1.1 Virtual Member Functions

Member function templates cannot be declared virtual. This constraint is imposed because the usual implementation of the virtual function call mechanism uses a fixed-size table with one entry per virtual function. However, the number of instantiations of a member function template is not fixed until the entire program has been translated. Hence, supporting virtual member function templates would require support for a whole new kind of mechanism in C++ compilers and linkers.

In contrast, the ordinary members of class templates can be virtual because their number is fixed when a class is instantiated:

template<typename T>
class Dynamic {
  public:
    virtual ~Dynamic();  // OK: one destructor per instance of Dynamic<T>

    template<typename T2>
    virtual void copy (T2 const&);
                        // ERROR: unknown number of instances of copy()
                        //        given an instance of Dynamic<T>
};

12.1.2 Linkage of Templates

Every template must have a name, and that name must be unique within its scope, except that function templates can be overloaded (see Chapter 16). Note especially that, unlike class types, class templates cannot share a name with a different kind of entity:

int C;

class C;    // OK: class names and nonclass names are in a different “space”

int X;

template<typename T>
class X;   // ERROR: conflict with variable X
struct S;

template<typename T>
class S;   // ERROR: conflict with struct S

Template names have linkage, but they cannot have C linkage. Nonstandard linkages may have an implementation-dependent meaning (however, we don’t know of an implementation that supports nonstandard name linkages for templates):

extern "C++" template<typename T>
void normal();           //this is the default: the linkage specification could be left out

extern "C" template<typename T>
void invalid();          //ERROR: templates cannot have C linkage
extern "Java" template<typename T>
void javaLink();         //nonstandard, but maybe some compiler will someday
                         // support linkage compatible with Java generics

Templates usually have external linkage. The only exceptions are namespace scope function templates with the static specifier, templates that are direct or indirect members of an unnamed name-space (which have internal linkage), and member templates of unnamed classes (which have no linkage). For example:

template<typename T>     // refers to the same entity as a declaration of the
void external();         // same name (and scope) in another file

template<typename T>     // unrelated to a template with the same name in
static void internal();  // another file

template<typename T>     // redeclaration of the previous declaration
static void internal();

namespace {
  template<typename>     // also unrelated to a template with the same name
  void otherInternal();  // in another file, even one that similarly appears
}                        //in an unnamed namespace

namespace {
  template<typename>     // redeclaration of the previous template declaration
  void otherInternal();
}

struct {
  template<typename T> void f(T) {}  //no linkage: cannot be redeclared
} x;

Note that since the latter member template has no linkage, it must be defined within the unnamed class because there is no way to provide a definition outside the class.

Currently templates cannot be declared in function scope or local class scope, but generic lambdas (see Section 15.10.6 on page 309), which have associated closure types that contain member function templates, can appear in local scopes, which effectively implies a kind of local member function template.

The linkage of an instance of a template is that of the template. For example, a function internal<void>() instantiated from the template internal declared above will have internal linkage. This has an interesting consequence in the case of variable templates. Indeed, consider the following example:

template<typename T> T zero = T{};

All instantiations of zero have external linkage, even something like zero<int const>. That’s perhaps counterintuitive given that

int const zero_int = int{};

has internal linkage because it is declared with a const type. Similarly, all instantiations of the template

template<typename T> int const max_volume = 11;

have external linkage, despite all those instantiations also having type int const.

12.1.3 Primary Templates

Normal declarations of templates declare primary templates. Such template declarations are declared without adding template arguments in angle brackets after the template name:

template<typename T> class Box;              // OK: primary template
template<typename T> class Box<T>;           // ERROR: does not specialize

template<typename T> void translate(T);      // OK: primary template
template<typename T> void translate<T>(T);   // ERROR: not allowed for functions

template<typename T> constexpr T zero = T{};     // OK: primary template
template<typename T> constexpr T zero<T> = T{};  // ERROR: does not specialize

Nonprimary templates occur when declaring partial specializations of class or variable templates. Those are discussed in Chapter 16. Function templates must always be primary templates (see Section 17.3 on page 356 for a discussion of a potential future language change).

12.2 Template Parameters

There are three basic kinds of template parameters:

1. Type parameters (these are by far the most common)

2. Nontype parameters

3. Template template parameters

Any of these basic kinds of template parameters can be used as the basis of a template parameter pack (see Section 12.2.4 on page 188).

Template parameters are declared in the introductory parameterization clause of a template declaration.1 Such declarations do not necessarily need to be named:

template<typename, int>
class X;    // X<> is parameterized by a type and an integer

A parameter name is, of course, required if the parameter is referred to later in the template. Note also that a template parameter name can be referred to in a subsequent parameter declaration (but not before):

template<typename T,             //the first parameter is used
         T Root,                 //in the declaration of the second one and
         template<T> class Buf>  // in the declaration of the third one
class Structure;

12.2.1 Type Parameters

Type parameters are introduced with either the keyword typename or the keyword class: The two are entirely equivalent.2 The keyword must be followed by a simple identifier, and that identifier must be followed by a comma to denote the start of the next parameter declaration, a closing angle bracket (>) to denote the end of the parameterization clause, or an equal sign (=) to denote the beginning of a default template argument.

Within a template declaration, a type parameter acts much like a type alias (see Section 2.8 on page 38). For example, it is not possible to use an elaborated name of the form class T when T is a template parameter, even if T were to be substituted by a class type:

template<typename Allocator>
class List {
    class Allocator* allocptr;     // ERROR: use “Allocator* allocptr
    friend class Allocator;        // ERROR: use “friend Allocator
    …
};

12.2.2 Nontype Parameters

Nontype template parameters stand for constant values that can be determined at compile or link time.3 The type of such a parameter (in other words, the type of the value for which it stands) must be one of the following:

• An integer type or an enumeration type

• A pointer type4

• A pointer-to-member type

• An lvalue reference type (both references to objects and references to functions are acceptable)

std::nullptr_t

• A type containing auto or decltype(auto) (since C++17 only; see Section 15.10.1 on page 296)

All other types are currently excluded (although floating-point types may be added in the future; see Section 17.2 on page 356).

Perhaps surprisingly, the declaration of a nontype template parameter can in some cases also start with the keyword typename:

template<typename T,                       //a type parameter
         typename T::Allocator* Allocator> // a nontype parameter
class List;

or with the keyword class:

template<class X*>    // a nontype parameter of pointer type
class Y;

The two cases are easily distinguished because the first is followed by a simple identifier and then one of a small set of tokens (’=’ for a default argument, ’,’ to indicate that another template parameter follows, or a closing > to end the template parameter list). Section 5.1 on page 67 and Section 13.3.2 on page 229 explain the need for the keyword typename in the first nontype parameter.

Function and array types can be specified, but they are implicitly adjusted to the pointer type to which they decay:

template<int buf[5]> class Lexer;         // buf is really an int*
template<int* buf> class Lexer;           // OK: this is a redeclaration

template<int fun()> struct FuncWrap;      // fun really has pointer to
                                          // function type
template<int (*)()> struct FuncWrap;      // OK: this is a redeclaration

Nontype template parameters are declared much like variables, but they cannot have nontype specifiers like static, mutable, and so forth. They can have const and volatile qualifiers, but if such a qualifier appears at the outermost level of the parameter type, it is simply ignored:

template<int const length> class Buffer; // const is useless here
template<int length> class Buffer;       // same as previous declaration

Finally, nonreference nontype parameters are always prvalues5 when used in expressions. Their address cannot be taken, and they cannot be assigned to. A nontype parameter of lvalue reference type, on the other hand, can be used to denote an lvalue:

template<int& Counter>
struct LocalIncrement {
  LocalIncrement() { Counter = Counter + 1; }   //OK: reference to an integer
  ~LocalIncrement() { Counter = Counter - 1; }
};

Rvalue references are not permitted.

12.2.3 Template Template Parameters

Template template parameters are placeholders for class or alias templates. They are declared much like class templates, but the keywords struct and union cannot be used:

template<template<typename X> class C>          // OK
void f(C<int>* p);

template<template<typename X> struct C>         // ERROR: struct not valid here
void f(C<int>* p);

template<template<typename X> union C>         // ERROR: union not valid here
void f(C<int>* p);

C++17 allows the use of typename instead of class: That change was motivated by the fact that template template parameters can be substituted not only by class templates but also by alias templates (which instantiate to arbitrary types). So, in C++17, our example above can be written instead as

template<template<typename X> typename C>        // OK since C++17
void f(C<int>* p);

In the scope of their declaration, template template parameters are used just like other class or alias templates.

The parameters of template template parameters can have default template arguments. These default arguments apply when the corresponding parameters are not specified in uses of the template template parameter:

template<template<typename T,
                  typename A = MyAllocator> class Container>
class Adaptation {
    Container<int> storage;  // implicitly equivalent to Container<int,MyAllocator>
    …
};

T and A are the names of the template parameter of the template template parameter Container. These names be used only in the declaration of other parameters of that template template parameter. The following contrived template illustrates this concept:

template<template<typename T, T*> class Buf>  // OK
class Lexer {
    static T* storage;  // ERROR: a template template parameter cannot be used here
    …
};

Usually however, the names of the template parameters of a template template parameter are not needed in the declaration of other template parameters and are therefore often left unnamed altogether. For example, our earlier Adaptation template could be declared as follows:

template<template<typename,
                  typename = MyAllocator> class Container>
class Adaptation {
    Container<int> storage; // implicitly equivalent to Container<int,MyAllocator>
    …
};

12.2.4 Template Parameter Packs

Since C++11, any kind of template parameter can be turned into a template parameter pack by introducing an ellipsis () prior to the template parameter name or, if the template parameter is unnamed, where the template parameter name would occur:

template<typename… Types>   // declares a template parameter pack named Types
class Tuple;

A template parameter pack behaves like its underlying template parameter, but with a crucial difference: While a normal template parameter matches exactly one template argument, a template parameter pack can match any number of template arguments. This means that the Tuple class template declared above accepts any number of (possibly distinct) types as template arguments:

using IntTuple = Tuple<int>;              // OK: one template argument
using IntCharTuple = Tuple<int, char>;    // OK: two template arguments
using IntTriple = Tuple<int, int, int>;   // OK: three template arguments
using EmptyTuple = Tuple<>;               // OK: zero template arguments

Similarly, template parameter packs of nontype and template template parameters can accept any number of nontype or template template arguments, respectively:

template<typename T, unsigned… Dimensions>
class MultiArray;       // OK: declares a nontype template parameter pack

using TransformMatrix = MultiArray<double, 3, 3>;   // OK: 3x3 matrix

template<typename T, template<typename,typename>… Containers>
void testContainers();  // OK: declares a template template parameter pack

The MultiArray example requires all nontype template arguments to be of the same type unsigned. C++17 introduced the possibility of deduced nontype template arguments, which allows us to work around that restriction to some extent—see Section 15.10.1 on page 298 for details.

Primary class templates, variable templates, and alias templates may have at most one template parameter pack and, if present, the template parameter pack must be the last template parameter. Function templates have a weaker restriction: Multiple template parameter packs are permitted, as long as each template parameter subsequent to a template parameter pack either has a default value (see the next section) or can be deduced (see Chapter 15):

template<typename… Types, typename Last>
class LastType;  // ERROR: template parameter pack is not the last template parameter

template<typename… TestTypes, typename T>
void runTests(T value);  // OK: template parameter pack is followed
                         //     by a deducible template parameter
template<unsigned…> struct Tensor;
template<unsigned… Dims1, unsigned… Dims2>
  auto compose(Tensor<Dims1…>, Tensor<Dims2…>);
                         // OK: the tensor dimensions can be deduced

The last example is the declaration of a function with a deduced return type—a C++14 feature. See also Section 15.10.1 on page 296.

Declarations of partial specializations of class and variable templates (see Chapter 16) can have multiple parameter packs, unlike their primary template counterparts. That is because partial specialization are selected through a deduction process that is nearly identical to that used for function templates.

template<typename…> Typelist;
template<typename X, typename Y> struct Zip;
template<typename… Xs, typename… Ys>
  struct Zip<Typelist<Xs…>, Typelist<Ys…>>;
          // OK: partial specialization uses deduction to determine
          //     theXs and Ys substitutions

Perhaps not surprisingly, a type parameter pack cannot be expanded in its own parameter clause. For example:

template<typename… Ts, Ts… vals> struct StaticValues {};
  // ERROR: Ts cannot be expanded in its own parameter list

However, nested templates can create similar valid situations:

template<typename… Ts> struct ArgList {
  template<Ts… vals> struct Vals {};
};
ArgList<int, char, char>::Vals<3, ’x’, ’y’> tada;

A template that contains a template parameter pack is called a variadic template because it accepts a variable number of template arguments. Chapter 4 and Section 12.4 on page 200 describe the use of variadic templates.

12.2.5 Default Template Arguments

Any kind of template parameter that is not a template parameter pack can be equipped with a default argument, although it must match the corresponding parameter in kind (e.g., a type parameter cannot have a nontype default argument). A default argument cannot depend on its own parameter, because the name of the parameter is not in scope until after the default argument. However, it may depend on previous parameters:

template<typename T, typename Allocator = allocator<T>>
class List;

A template parameter for a class template, variable template, or alias template can have a default template argument only if default arguments were also supplied for the subsequent parameters. (A similar constraint exists for default function call arguments.) The subsequent default values are usually provided in the same template declaration, but they could also have been declared in a previous declaration of that template. The following example makes this clear:

template<typename T1, typename T2, typename T3,
         typename T4 = char, typename T5 = char>
class Quintuple;  // OK

template<typename T1, typename T2, typename T3 = char,
         typename T4, typename T5>
class Quintuple;  // OK: T4 and T5 already have defaults

template<typename T1 = char, typename T2, typename T3,
         typename T4, typename T5>
class Quintuple;  // ERROR: T1 cannot have a default argument
                  // because T2 doesn’t have a default

Default template arguments for template parameters of function templates do not require subsequent template parameters to have a default template argument:6

template<typename R = void, typename T>
R* addressof(T& value);  // OK: if not explicitly specified, R will be void

Default template arguments cannot be repeated:

template<typename T = void>
class Value;

template<typename T = void>
class Value;  // ERROR: repeated default argument

A number of contexts do not permit default template arguments:

• Partial specializations:

template<typename T>
class C;

template<typename T = int>
class C<T*>;                                        // ERROR

• Parameter packs:

template<typename… Ts = int> struct X;        // ERROR

• The out-of-class definition of a member of a class template:

template<typename T> struct X
{
  T f();
};

template<typename T = int> T X<T>::f() {          // ERROR
  …
}

• A friend class template declaration:

struct S {
 template<typename = void> friend struct F;
};

• A friend function template declaration unless it is a definition and no declaration of it appears anywhere else in the translation unit:

struct S {
 template<typename = void> friend void f();    // ERROR: not a definition
 template<typename = void> friend void g() {   //OK so far
 }
};
template<typename> void g();  // ERROR: g() was given a default template argument
                              // when defined; no other declaration may exist here

12.3 Template Arguments

When instantiating a template, template parameters are substituted by template arguments. The arguments can be determined using several different mechanisms:

• Explicit template arguments: A template name can be followed by explicit template arguments enclosed in angle brackets. The resulting name is called a template-id.

• Injected class name: Within the scope of a class template X with template parameters P1, P2, … , the name of that template (X) can be equivalent to the template-id X<P1, P2,>. See Section 13.2.3 on page 221 for details.

• Default template arguments: Explicit template arguments can be omitted from template instances if default template arguments are available. However, for a class or alias template, even if all template parameters have a default value, the (possibly empty) angle brackets must be provided.

• Argument deduction: Function template arguments that are not explicitly specified may be deduced from the types of the function call arguments in a call. This is described in detail in Chapter 15. Deduction is also done in a few other situations. If all the template arguments can be deduced, no angle brackets need to be specified after the name of the function template. C++17 also introduces the ability to deduce class template arguments from the initializer of a variable declaration or functional-notation type conversion; see Section 15.12 on page 313 for a discussion.

12.3.1 Function Template Arguments

Template arguments for a function template can be specified explicitly, deduced from the way the template is used, or provided as a default template argument. For example:

details/max.cpp

template<typename T>
T max (T a, T b)
{
   return b < a ? a : b;
}

int main()
{
  ::max<double>(1.0, -3.0);  // explicitly specify template argument
  ::max(1.0, -3.0);          // template argument is implicitly deduced to be double
  ::max<int>(1.0, 3.0);      // the explicit <int> inhibits the deduction;
                             // hence the result has type int
}

Some template arguments can never be deduced because their corresponding template parameter does not appear in a function parameter type or for some other reason (see Section 15.2 on page 271). The corresponding parameters are typically placed at the beginning of the list of template parameters so they can be specified explicitly while allowing the other arguments to be deduced. For example:

details/implicit.cpp

template<typename DstT, typename SrcT>
DstT implicit_cast (SrcT const& x) // SrcT can be deduced, but DstT cannot
{
  return x;
}

int main()
{
  double value = implicit_cast<double>(-1);
}

If we had reversed the order of the template parameters in this example (in other words, if we had written template<typename SrcT, typename DstT>), a call of implicit_cast would have to specify both template arguments explicitly.

Moreover, such parameters can’t usefully be placed after a template parameter pack or appear in a partial specialization, because there would be no way to explicitly specify or deduce them.

template<typename … Ts, int N>
void f(double (&)[N+1], Ts … ps);  // useless declaration because N
                                     // cannot be specified or deduced

Because function templates can be overloaded, explicitly providing all the arguments for a function template may not be sufficient to identify a single function: In some cases, it identifies a set of functions. The following example illustrates a consequence of this observation:

template<typename Func, typename T>
void apply (Func funcPtr, T x)
{
    funcPtr(x);
}

template<typename T> void single(T);

template<typename T> void multi(T);
template<typename T> void multi(T*);

int main()
{
    apply(&single<int>, 3);  // OK
    apply(&multi<int>, 7);   // ERROR: no single multi<int>
}

In this example, the first call to apply() works because the type of the expression &single<int> is unambiguous. As a result, the template argument value for the Func parameter is easily deduced. In the second call, however, &multi<int> could be one of two different types and therefore Func cannot be deduced in this case.

Furthermore, it is possible that substituting template arguments in a function template results in an attempt to construct an invalid C++ type or expression. Consider the following overloaded function template (RT1 and RT2 are unspecified types):

template<typename T> RT1 test(typename T::X const*);
template<typename T> RT2 test(…);

The expression test<int> makes no sense for the first of the two function templates because type int has no member type X. However, the second template has no such problem. Therefore, the expression &test<int> identifies the address of a single function. The fact that the substitution of int into the first template fails does not make the expression invalid. This SFINAE (substitution failure is not an error) principle is an important ingredient to make the overloading of function templates practical and is discussed in Section 8.4 on page 129 and Section 15.7 on page 284.

12.3.2 Type Arguments

Template type arguments are the “values” specified for template type parameters. Any type (including void, function types, reference types, etc.) can, in general, be used as a template argument, but their substitution for the template parameters must lead to valid constructs:

template<typename T>
void clear (T p)
{
    *p = 0;    // requires that the unary * be applicable to T
}

int main()
{
    int a;
    clear(a);  // ERROR: int doesn’t support the unary *
}

12.3.3 Nontype Arguments

Nontype template arguments are the values substituted for nontype parameters. Such a value must be one of the following things:

• Another nontype template parameter that has the right type.

• A compile-time constant value of integer (or enumeration) type. This is acceptable only if the corresponding parameter has a type that matches that of the value or a type to which the value can be implicitly converted without narrowing. For example, a char value can be provided for an int parameter, but 500 is not valid for an 8-bit char parameter.

• The name of an external variable or function preceded by the built-in unary & (“address of”) operator. For functions and array variables, & can be left out. Such template arguments match nontype parameters of a pointer type. C++17 relaxed this requirement to permit any constant-expression that produces a pointer to a function or variable.

• The previous kind of argument but without a leading & operator is a valid argument for a nontype parameter of reference type. Here too, C++17 relaxed the constraint to permit any constant-expression glvalue for a function or variable.

• A pointer-to-member constant; in other words, an expression of the form &C::m where C is a class type and m is a nonstatic member (data or function). This matches nontype parameters of pointer-to-member type only. And again, in C++17, the actual syntactic form is no longer constrained: Any constant-expression evaluating to a matching pointer-to-member constant is permitted.

• A null pointer constant is a valid argument for a nontype parameter of pointer or pointer-to-member type.

For nontype parameters of integral type—probably the most common kind of nontype parameter— implicit conversions to the parameter type are considered. With the introduction of constexpr conversion functions in C++11, this means that the argument before conversion can have a class type.

Prior to C++17, when matching an argument to a parameter that is a pointer or reference, user-defined conversions (constructors for one argument and conversion operators) and derived-to-base conversions are not considered, even though in other circumstances they would be valid implicit conversions. Implicit conversions that make an argument more const and/or more volatile are fine.

Here are some valid examples of nontype template arguments:

template<typename T, T nontypeParam>
class C;

C<int, 33>* c1;        // integer type
int a;
C<int*, &a>* c2;        // address of an external variable

void f();
void f(int);
C<void (*)(int), f>* c3;  // name of a function: overload resolution selects
                          // f(int) in this case; the & is implied

template<typename T> void templ_func();
C<void(), &templ_func<double>>* c4;  // function template instantiations are functions
struct X {
    static bool b;
    int n;
    constexpr operator int() const { return 42; }
};

C<bool&, X::b>* c5;      // static class members are acceptable variable/function names

C<int X::*, &X::n>* c6;  // an example of a pointer-to-member constant

C<long, X{}>* c7;        // OK: X is first converted to int via a constexpr conversion
                         // function and then to long via a standard integer conversion

A general constraint of template arguments is that a compiler or a linker must be able to express their value when the program is being built. Values that aren’t known until a program is run (e.g., the address of local variables) aren’t compatible with the notion that templates are instantiated when the program is built.

Even so, there are some constant values that are, perhaps surprisingly, not currently valid:

• Floating-point numbers

• String literals (Prior to C++11, null pointer constants were not permitted either.)

One of the problems with string literals is that two identical literals can be stored at two distinct addresses. An alternative (but cumbersome) way to express templates instantiated over constant strings involves introducing an additional variable to hold the string:

template<char const* str>
class Message {
  …
};

extern char const hello[] = "Hello World!";
char const hello11[] = "Hello World!";

void foo()
{
  static char const hello17[] = "Hello World!";

  Message<hello> msg03;     // OK in all versions
  Message<hello11> msg11;   // OK since C++11
  Message<hello17> msg17;   // OK since C++17
}

The requirement is that a nontype template parameter declared as reference or pointer can be a constant expression with external linkage in all C++ versions, internal linkage since C++11, or any linkage since C++17.

See Section 17.2 on page 354 for a discussion of possible future changes in this area

Here are a few other (less surprising) invalid examples:

template<typename T, T nontypeParam>
class C;

struct Base {
    int i;
} base;

struct Derived : public Base {
} derived;

C<Base*, &derived>* err1; // ERROR: derived-to-base conversions are not considered

C<int&, base.i>* err2;    // ERROR: fields of variables aren’t considered to be variables

int a[10];
C<int*, &a[0]>* err3;     // ERROR: addresses of array elements aren’t acceptable either

12.3.4 Template Template Arguments

A template template argument must generally be a class template or alias template with parameters that exactly match the parameters of the template template parameter it substitutes. Prior to C++17, default template arguments of a template template argument were ignored (but if the template template parameter has default arguments, they are considered during the instantiation of the template). C++17 relaxed the matching rule to just require that the template template parameter be at least as specialized (see Section 16.2.2 on page 330) as the corresponding template template argument.

This makes the following example invalid prior to C++17:

#include <list>
    // declares in namespace std:
    // template<typename T, typename Allocator = allocator<T>>
    // class list;

template<typename T1, typename T2,
         template<typename> class Cont>  // Cont expects one parameter
class Rel {
    …
};

Rel<int, double, std::list> rel;  // ERROR before C++17: std::list has more than
                                  //                     one template parameter

The problem in this example is that the std::list template of the standard library has more than one parameter. The second parameter (which describes an allocator) has a default value, but prior to C++17, that is not considered when matching std::list to the Container parameter.

Variadic template template parameters are an exception to the pre-C++17 “exact match” rule described above and offer a solution to this limitation: They enable more general matching against template template arguments. A template template parameter pack can match zero or more template parameters of the same kind in the template template argument:

#include <list>

template<typename T1, typename T2,
         template<typename… > class Cont>  // Cont expects any number of
class Rel {                                  // type parameters
   …
};

Rel<int, double, std::list> rel;  // OK: std::list has two template parameters
                                  //     but can be used with one argument

Template parameter packs can only match template arguments of the same kind. For example, the following class template can be instantiated with any class template or alias template having only template type parameters, because the template type parameter pack passed there as TT can match zero or more template type parameters:

#include <list>
#include <map>
    // declares in namespace std:
    //  template<typename Key, typename T,
    //           typename Compare = less<Key>,
    //           typename Allocator = allocator<pair<Key const, T>>>
    //  class map;
#include <array>
    // declares in namespace std:
    //  template<typename T, size_t N>
    //  class array;

template<template<typename… > class TT>
class AlmostAnyTmpl {
};

AlmostAnyTmpl<std::vector> withVector; //two type parameters
AlmostAnyTmpl<std::map> withMap;       // four type parameters
AlmostAnyTmpl<std::array> withArray;   // ERROR: a template type parameter pack
                                       // doesn’t match a nontype template parameter

The fact that, prior to C++17, only the keyword class could be used to declare a template template parameter does not indicate that only class templates declared with the keyword class were allowed as substituting arguments. Indeed, struct, union, and alias templates are all valid arguments for a template template parameter (alias templates since C++11, when they were introduced). This is similar to the observation that any type can be used as an argument for a template type parameter declared with the keyword class.

12.3.5 Equivalence

Two sets of template arguments are equivalent when values of the arguments are identical one-forone. For type arguments, type aliases don’t matter: It is the type ultimately underlying the type alias declaration that is compared. For integer nontype arguments, the value of the argument is compared; how that value is expressed doesn’t matter. The following example illustrates this concept:

template<typename T, int I>
class Mix;

using Int = int;

Mix<int, 3*3>* p1;
Mix<Int, 4+5>* p2;  // p2 has the same type as p1

(As is clear from this example, no template definition is needed to establish the equivalence of the template argument lists.)

In template-dependent contexts, however, the “value” of a template argument cannot always be established definitely, and the rules for equivalence become a little more complicated. Consider the following example:

template<int N> struct I {};

template<int M, int N> void f(I<M+N>);  // #1
template<int N, int M> void f(I<N+M>);  // #2

template<int M, int N> void f(I<N+M>);  // #3 ERROR

Study declarations #1 and #2 carefully, and you’ll notice that by just renaming M and N to, respectively, N and M, you obtain the same declaration: The two are therefore equivalent and declare the same function template f. The expressions M+N and N+M in those two declarations are called equivalent.

Declaration #3 is, however, subtly different: The order of the operands is inverted. That makes the expression N+M in #3 not equivalent to either of the other two expressions. However, because the expression will produce the same result for any values of the template parameters involved, those expressions are called functionally equivalent. It is an error for templates to be declared in ways that differ only because the declarations include functionally equivalent expressions that are not actually equivalent. However, such an error need not be diagnosed by your compiler. That’s because some compilers may, for example, internally represent N+1+1 in exactly the same way as N+2, whereas other compilers may not. Rather than impose a specific implementation approach, the standard allows either one and requires programmers to be careful in this area.

A function generated from a function template is never equivalent to an ordinary function even though they may have the same type and the same name. This has two important consequences for class members:

1. A function generated from a member function template never overrides a virtual function.

2. A constructor generated from a constructor template is never a copy or move constructor.7 Similarly, an assignment generated from an assignment template is never a copy-assignment or move-assignment operator. (However, this is less prone to problems because implicit calls of copy-assignment or move-assignment operators are less common.)

This can be good and bad. See Section 6.2 on page 95 and Section 6.4 on page 102 for details.

12.4 Variadic Templates

Variadic templates, introduced in Section 4.1 on page 55, are templates that contain at least one template parameter pack (see Section 12.2.4 on page 188).8 Variadic templates are useful when a template’s behavior can be generalized to any number of arguments. The Tuple class template introduced in Section 12.2.4 on page 188 is one such type, because a tuple can have any number of elements, all of which are treated the same way. We can also imagine a simple print() function that takes any number of arguments and displays each of them in sequence.

When template arguments are determined for a variadic template, each template parameter pack in the variadic template will match a sequence of zero or more template arguments. We refer to this sequence of template arguments as an argument pack. The following example illustrates how the template parameter pack Types matches to different argument packs depending on the template arguments provided for Tuple:

template<typename… Types>
class Tuple {
  // provides operations on the list of types in Types
};

int main() {
  Tuple<> t0;           // Types contains an empty list
  Tuple<int> t1;        // Types contains int
  Tuple<int, float> t2; //  Types contains int and float
}

Because a template parameter pack represents a list of template arguments rather than a single template argument, it must be used in a context where the same language construct applies to all of the arguments in the argument pack. One such construct is the sizeof… operation, which counts the number of arguments in the argument pack:

template<typename… Types>
class Tuple {
  public:
    static constexpr std::size_t length = sizeof…(Types);
};

int a1[Tuple<int>::length];              // array of one integer
int a3[Tuple<short, int, long>::length]; // array of three integers

12.4.1 Pack Expansions

The sizeof… expression is an example of a pack expansion. A pack expansion is a construct that expands an argument pack into separate arguments. While sizeof… performs this expansion just to count the number of separate arguments, other forms of parameter packs—those that occur where C++ expects a list—can expand to multiple elements within that list. Such pack expansions are identified by an ellipsis () to the right of an element in the list. Here is a simple example where we create a new class template MyTuple that derives from Tuple, passing along its arguments:

template<typename… Types>
class MyTuple : public Tuple<Types…> {
  // extra operations provided only for MyTuple
};

MyTuple<int, float> t2;  // inherits from Tuple<int, float>

The template argument Types… is a pack expansion that produces a sequence of template arguments, one for each argument within the argument pack substituted for Types. As illustrated in the example, the instantiation of type MyTuple<int, float> substitutes the argument pack int, float for the template type parameter pack Types. When this occurs in the pack expansion Types…, we get one template argument for int and one for float, so MyTuple<int, float> inherits from Tuple<int, float>.

An intuitive way to understand pack expansions is to think of them in terms of a syntactic expansion, where template parameter packs are replaced with exactly the right number of (non-pack) template parameters and pack expansions are written out as separate arguments, once for each of the non-pack template parameters. For example, here is how MyTuple would look if it were expanded for two parameters:9

template<typename T1, typename T2>
class MyTuple : public Tuple<T1, T2> {
  // extra operations provided only for MyTuple
};

and for three parameters:

template<typename T1, typename T2, typename T3>
class MyTuple : public Tuple<T1, T2, T3> {
  // extra operations provided only for MyTuple
};

However, note that you can’t access the individual elements of a parameter pack directly by name, because names such as T1, T2, and so on, are not defined in a variadic template. If you need the types, the only thing you can do is to pass them (recursively) to another class or function.

Each pack expansion has a pattern, which is the type or expression that will be repeated for each argument in the argument pack and typically comes before the ellipsis that denotes the pack expansion. Our prior examples have had only trivial patterns—the name of the parameter pack—but patterns can be arbitrarily complex. For example, we can define a new type PtrTuple that derives from a Tuple of pointers to its argument types:

template<typename… Types>
class PtrTuple : public Tuple<Types*…> {
  // extra operations provided only for PtrTuple
};

PtrTuple<int, float> t3; // Inherits from Tuple<int*, float*>

The pattern for the pack expansion Types*… in the example above is Types*. Repeated substitution into this pattern produces a sequence of template type arguments, all of which are pointers to the types in the argument pack substituted for Types. Under the syntactic interpretation of pack expansions, here is how PtrTuple would look if it were expanded for three parameters:

template<typename T1, typename T2, typename T3>
class PtrTuple : public Tuple<T1*, T2*, T3*> {
  // extra operations provided only for PtrTuple
};

12.4.2 Where Can Pack Expansions Occur?

Our examples thus far have focused on the use of pack expansions to produce a sequence of template arguments. In fact, pack expansions can be used essentially anywhere in the language where the grammar provides a comma-separated list, including:

• In the list of base classes.

• In the list of base class initializers in a constructor.

• In a list of call arguments (the pattern is the argument expression).

• In a list of initializers (e.g., in a braced initializer list).

• In the template parameter list of a class, function, or alias template.

• In the list of exceptions that can be thrown by a function (deprecated in C++11 and C++14, and disallowed in C++17).

• Within an attribute, if the attribute itself supports pack expansions (although no such attribute is defined by the C++ standard).

• When specifying the alignment of a declaration.

• When specifying the capture list of a lambda.

• In the parameter list of a function type.

• In using declarations (since C++17; see Section 4.4.5 on page 65). We’ve already mentioned sizeof… as a pack-expansion mechanism that does not actually produce a list. C++17 also adds fold expressions, which are another mechanism that does not produce a comma-separated list (see Section 12.4.6 on page 207.

Some of these pack-expansion contexts are included merely for the sake of completeness, so we will focus our attention on only those pack-expansion contexts that tend to be useful in practice. Since pack expansions in all contexts follow the same principles and syntax, you should be able to extrapolate from the examples given here should you find a need for the more esoteric pack-expansion contexts.

A pack expansion in a list of base classes expands to some number of direct base classes. Such expansions can be useful to aggregate externally supplied data and functionality via mixins, which are classes intended to be “mixed into” a class hierarchy to provide new behaviors. For example, the following Point class uses pack expansions in several different contexts to allow arbitrary mixins:10

template<typename… Mixins>
class Point : public Mixins… {    //base class pack expansion
  double x, y, z;
 public:
  Point() : Mixins()… { }         // base class initializer pack expansion

  template<typename Visitor>
  void visitMixins(Visitor visitor) {
    visitor(static_cast<Mixins&>(*this)…); // call argument pack expansion
  }
};

struct Color { char red, green, blue; };
struct Label { std::string name; };
Point<Color, Label> p;             // inherits from both Color and Label

The Point class uses a pack expansion to take each of the supplied mixins and expand it into a public base class. The default constructor of Point then applies a pack expansion in the base initializer list to value-initialize each of the base classes introduced via the mixin mechanism.

The member function template visitMixins is the most interesting in that it uses the results of a pack expansion as arguments to a call. By casting *this to each of the mixin types, the pack expansion produces call arguments that refer to each of the base classes corresponding to the mixins. Actually writing a visitor for use with visitMixins, which can make use of such an arbitrary number of function call arguments, is covered in Section 12.4.3 on page 204.

A pack expansion can also be used within a template parameter list to create a nontype or template parameter pack:

template<typename… Ts>
struct Values {
  template<Ts… Vs>
  struct Holder {
  };
};

int i;
Values<char, int, int*>::Holder<’a’, 17, &i> valueHolder;

Note that once the type arguments for Values<…> have been specified, the nontype argument list for Values<…>::Holder has a fixed length; the parameter pack Vs is thus not a variable-length parameter pack.

Values is a nontype template parameter pack for which each of the actual template arguments can have a different type, as specified by the types provided for the template type parameter pack Types. Note that the ellipsis in the declaration of Values plays a dual role, both declaring the template parameter as a template parameter pack and declaring the type of that template parameter pack as a pack expansion. While such template parameter packs are rare in practice, the same principle applies in a much more general context: function parameters.

12.4.3 Function Parameter Packs

A function parameter pack is a function parameter that matches zero or more function call arguments. Like a template parameter pack, a function parameter pack is introduced using an ellipsis () prior to (or in the place of) the function parameter name and, also like a template parameter pack, a function parameter pack must be expanded by a pack expansion whenever it is used. Template parameter packs and function parameter packs together are referred to as parameter packs.

Unlike template parameter packs, function parameter packs are always pack expansions, so their declared types must include at least one parameter pack. In the following example, we introduce a new Point constructor that copy-initializes each of the mixins from supplied constructor arguments:

template<typename… Mixins>
class Point : public Mixins…
{
  double x, y, z;
 public:
  //default constructor, visitor function, etc. elided
  Point(Mixins… mixins)    // mixins is a function parameter pack
    : Mixins(mixins)… { }  //initialize each base with the supplied mixin value
};

struct Color { char red, green, blue; };
struct Label { std::string name; };
Point<Color, Label> p({0x7F, 0, 0x7F}, {"center"});

A function parameter pack for a function template may depend on template parameter packs declared in that template, which allows the function template to accept an arbitrary number of call arguments without losing type information:

template<typename… Types>
void print(Types… values);

int main
{
  std::string welcome("Welcome to ");
  print(welcome, "C++", 2011, ’\n’); //calls print<std::string, char const*,
}                                    //            int, char>

When calling the function template print() with some number of arguments, the types of the arguments will be placed in the argument pack to be substituted for the template type parameter pack Types, while the actual argument values will be placed into an argument pack to be substituted for the function parameter pack values. The process by which the arguments are determined from the call is described in detail in Chapter 15. For now, it suffices to note that the ith type in Types is the type of the ith value in Values and that both of these parameter packs are available within the body of the function template print().

The actual implementation of print() uses recursive template instantiation, a template metaprogramming technique described in Section 8.1 on page 123 and Chapter 23.

There is a syntactic ambiguity between an unnamed function parameter pack appearing at the end of a parameter list and a C-style “vararg” parameter. For example:

template<typename T> void c_style(int, T…);
template<typename… T> void pack(int, T…);

In the first case, the “T…” is treated as “T, …”: an unnamed parameter of type T followed by a C-style vararg parameter. In the second case, the “T…” construct is treated as a function parameter pack because T is a valid expansion pattern. The disambiguation can be forced by adding a comma before the ellipsis (which ensures the ellipsis is treated as a C-style “vararg” parameter) or by following the by an identifier, which makes it a named function parameter pack. Note that in generic lambdas, a trailing will be treated as denoting a parameter pack if the type that immediately precedes it (with no intervening comma) contains auto.

12.4.4 Multiple and Nested Pack Expansions

The pattern of a pack expansion can be arbitrarily complex and may include multiple, distinct parameter packs. When instantiating a pack expansion containing multiple parameter packs, all of the parameter packs must have the same length. The resulting sequence of types or values will be formed element-wise by substituting the first argument of each parameter pack into the pattern, followed by the second argument of each parameter pack, and so on. For example, the following function copies all of its arguments before forwarding them on to the function object f:

template<typename F, typename… Types>
void forwardCopy(F f, Types const&… values) {
  f(Types(values)…);
}

The call argument pack expansion names two parameters packs, Types and values. When instantiating this template, the element-wise expansion of the Types and values parameter packs produces a series of object constructions, which builds a copy of the ith value in values by casting it to the ith type in Types. Under the syntactic interpretation of pack expansions, a three-argument forwardCopy would look like this:

template<typename F, typename T1, typename T2, typename T3>
void forwardCopy(F f, T1 const& v1, T2 const& v2, T3 const& v3) {
  f(T1(v1), T2(v2), T3(v3));
}

Pack expansions themselves may also be nested. In such cases, each occurrence of a parameter pack is “expanded” by its nearest enclosing pack expansion (and only that pack expansion). The following examples illustrates a nested pack expansion involving three different parameter packs:

template<typename… OuterTypes>
class Nested {
  template<typename… InnerTypes>
  void f(InnerTypes const&… innerValues) {
    g(OuterTypes(InnerTypes(innerValues)…)…);
  }
};

In the call to g(), the pack expansion with pattern InnerTypes(innerValues) is the innermost pack expansion, which expands both InnerTypes and innerValues and produces a sequence of function call arguments for the initialization of an object denoted by OuterTypes. The outer pack expansion’s pattern includes the inner pack expansion, producing a set of call arguments for the function g(), created from the initialization of each of the types in OuterTypes from the sequence of function call arguments produced by the inner expansion. Under the syntactic interpretation of this pack expansion, where OuterTypes has two arguments and both InnerTypes and innerValues have three arguments, the nesting becomes more apparent:

template<typename O1, typename O2>
class Nested {
  template<typename I1, typename I2, typename I3>
  void f(I1 const& iv1, I2 const& iv2, I3 const& iv3) {
    g(O1(I1(iv1), I2(iv2), I3(iv3)),
      O2(I1(iv1), I2(iv2), I3(iv3)),
      O3(I1(iv1), I2(iv2), I3(iv3)));
  }
};

Multiple and nested pack expansions are a powerful tool (e.g., see Section 26.2 on page 608).

12.4.5 Zero-Length Pack Expansions

The syntactic interpretation of pack expansions can be a useful tool for understanding how an instantiation of a variadic template will behave with different numbers of arguments. However, the syntactic interpretation often fails in the presence of zero-length argument packs. To illustrate this, consider the Point class template from Section 12.4.2 on page 202, syntactically substituted with zero arguments:

template<>
class Point : {
  Point() : { }
};

The code as written above is ill-formed, since the template parameter list is now empty and the empty base class and base class initializer lists each have a stray colon character.

Pack expansions are actually semantic constructs, and the substitution of an argument pack of any size does not affect how the pack expansion (or its enclosing variadic template) is parsed. Rather, when a pack expansion expands to an empty list, the program behaves (semantically) as if the list were not present. The instantiation Point<> ends up having no base classes, and its default constructor has no base class initializers but is otherwise well-formed. This semantic rules holds even when the syntactic interpretation of zero-length pack expansion would be well-defined (but different) code. For example:

template<typename T, typename… Types>
void g(Types… values) {
  T v(values…);
}

The variadic function template g() creates a value v that is direct-initialized from the sequence of values it is given. If that sequence of values is empty, the declaration of v looks, syntactically, like a function declaration T v(). However, since substitution into a pack expansion is semantic and cannot affect the kind of entity produced by parsing, v is initialized with zero arguments, that is, value-initialization.11

12.4.6 Fold Expressions

A recurring pattern in programming is the fold of an operation on a sequence of values. For example, a right fold of a function fn over a sequence x[1], x[2], …, x[n-1], x[n] is given by fn(x[1], fn(x[2], fn(, fn(x[n-1], x[n])))) While exploring a new language feature, the C++ committee ran into the need to deal with such constructs for the special case of a logical binary operator (i.e., && or ||) applied to a pack expansion. Without an extra feature, we might write the following code to achieve that for the && operator:

bool and_all() { return true; }
template<typename T>
  bool and_all(T cond) { return cond; }
template<typename T, typename… Ts>
  bool and_all(T cond, Ts… conds) {
    return cond && and_all(conds…);
}

With C++17, a new feature called fold expressions was added (see Section 4.2 on page 58 for an introduction). It applies to all binary operators except ., ->, and [].

Given an unexpanded expression pattern pack and a nonpattern expression value, C++17 allows us to write for any such operator op, either

(pack opop value)

for a right fold of the operator (called a binary right fold), or

(value opop pack)

for a left fold (called a binary left fold). Note that the parentheses are required here. See Section 4.2 on page 58 for some basic examples.

The fold operation applies to the sequence that results from expanding the pack and adding value as either the last element of the sequence (for a right fold) or the first element of the sequence (for a left fold).

With this feature available, code like

template<typename… T> bool g() {
  return and_all(trait<T>()…);
}

(where and_all is as defined above), can instead be written as

template<typename… T> bool g() {
  return (trait<T>() && … && true);
}

As you’d expect, fold expressions are pack expansions. Note that if the pack is empty, the type of the fold expression can still be determined from the non-pack operand (value in the forms above).

However, the designers of this feature also wanted an option to leave out the value operand. Two other forms are therefore available in C++17: The unary right fold

(pack op … )

and the unary left fold

(… op pack)

Again, the parentheses are required. Clearly this creates a problem for empty expansions: How do we determine their type and value? The answer is that an empty expansion of a unary fold is generally an error, with three exceptions:

• An empty expansion of a unary fold of && produces the value true,.

• An empty expansion of a unary fold of || produces the value false.

• An empty expansion of a unary fold of the comma operator (,) produces a void expression.

Note that this will create surprises if you overload one of these special operators in a somewhat unusual way. For example:

struct BooleanSymbol {
  …
};

BooleanSymbol operator||(BooleanSymbol, BooleanSymbol);

template<typename… BTs> void symbolic(BTs… ps) {
  BooleanSymbol result = (ps || …);
  …
}

Suppose we call symbolic with types that are derived from BooleanSymbol. For all expansions, the result will produce a BooleanSymbol value except for the empty expansion, which will produce a bool value.12 We therefore generally caution against the use of unary fold expressions, and recommend using binary fold expressions instead (with an explicitly specified empty expansion value).

12.5 Friends

The basic idea of friend declarations is a simple one: Identify classes or functions that have a privileged connection with the class in which the friend declaration appears. Matters are somewhat complicated, however, by two facts:

1. A friend declaration may be the only declaration of an entity.

2. A friend function declaration can be a definition.

12.5.1 Friend Classes of Class Templates

Friend class declarations cannot be definitions and therefore are rarely problematic. In the context of templates, the only new facet of friend class declarations is the ability to name a particular instance of a class template as a friend:

template<typename T>
class Node;

template<typename T>
class Tree {
    friend class Node<T>;
    …
};

Note that the class template must be visible at the point where one of its instances is made a friend of a class or class template. With an ordinary class, there is no such requirement:

template<typename T>
class Tree {
    friend class Factory;  // OK even if first declaration of Factory
    friend class Node<T>;  // error if Node isn’t visible
};

Section 13.2.2 on page 220 has more to say about this.

One application, introduced in Section 5.5 on page 75, is the declaration of other class template instantiations to be friends:

template<typename T>
class Stack {
  public:
   …
   // assign stack of elements of type T2
   template<typename T2>
   Stack<T>& operator= (Stack<T2> const&);
   // to get access to private members of Stack<T2> for any type T2:
   template<typename> friend class Stack;
   …
};

C++11 also added syntax to make a template parameter a friend:

template<typename T>
class Wrap {
  friend T;
  …
};

This is valid for any type T but is ignored if T is not actually a class type.13

12.5.2 Friend Functions of Class Templates

An instance of a function template can be made a friend by making sure the name of the friend function is followed by angle brackets. The angle brackets can contain the template arguments, but if the arguments can be deduced, the angle brackets can be left empty:

template<typename T1, typename T2>
void combine(T1, T2);

class Mixer {
    friend void combine<>(int&, int&);
                       // OK: T1 = int&, T2 = int&
    friend void combine<int, int>(int, int);
                       // OK: T1 = int, T2 = int
    friend void combine<char>(char, int);
                       // OK: T1 = char T2 = int
    friend void combine<char>(char&, int);
                       // ERROR: doesn’t match combine() template
    friend void combine<>(long, long) { … }
                       // ERROR: definition not allowed!
};

Note that we cannot define a template instance (at most, we can define a specialization), and hence a friend declaration that names an instance cannot be a definition.

If the name is not followed by angle brackets, there are two possibilities:

1. If the name isn’t qualified (in other words, it doesn’t contain ::), it never refers to a template instance. If no matching nontemplate function is visible at the point of the friend declaration, the friend declaration is the first declaration of that function. The declaration could also be a definition.

2. If the name is qualified (it contains ::), the name must refer to a previously declared function or function template. A matching function is preferred over a matching function template. However, such a friend declaration cannot be a definition. An example may help clarify the various possibilities:

void multiply(void*);    // ordinary function

template<typename T>
void multiply(T);        // function template

class Comrades {
    friend void multiply(int) { }
                         // defines a new function ::multiply(int)

    friend void ::multiply(void*);
                         // refers to the ordinary function above,
                         // not to the multiply<void*> instance
    friend void ::multiply(int);
                         // refers to an instance of the template

    friend void ::multiply<double*>(double*);
                         // qualified names can also have angle brackets,
                         // but a template must be visible
    friend void ::error() { }
                         // ERROR: a qualified friend cannot be a definition
};

In our previous examples, we declared the friend functions in an ordinary class. The same rules apply when we declare them in class templates, but the template parameters may participate in identifying the function that is to be a friend:

template<typename T>
class Node {
    Node<T>* allocate();
    …
};

template<typename T>
class List {
    friend Node<T>* Node<T>::allocate();
    …
};

A friend function may also be defined within a class template, in which case it is only instantiated when it is actually used. This typically requires the friend function to use the class template itself in the type of the friend function, which makes it easier to express functions on the class template that can be called as if they were visible in namespace scope:

template<typename T>
class Creator {
  friend void feed(Creator<T>) {  //every T instantiates a different function ::feed()
    …
  }
};

int main()
{
  Creator<void> one;
  feed(one);                     // instantiates ::feed(Creator<void>)
  Creator<double> two;
  feed(two);                     // instantiates ::feed(Creator<double>)
}

In this example, every instantiation of Creator generates a different function. Note that even though these functions are generated as part of the instantiation of a template, the functions themselves are ordinary functions, not instances of a template. However, they are considered templated entities (see Section 12.1 on page 181) and their definition is instantiated only when used. Also note that because the body of these functions is defined inside a class definition, they are implicitly inline. Hence, it is not an error for the same function to be generated in two different translation units. Section 13.2.2 on page 220 and Section 21.2.1 on page 497 have more to say about this topic.

12.5.3 Friend Templates

Usually when declaring a friend that is an instance of a function or a class template, we can express exactly which entity is to be the friend. Sometimes it is nonetheless useful to express that all instances of a template are friends of a class. This requires a friend template. For example:

class Manager {
    template<typename T>
      friend class Task;

    template<typename T>
      friend void Schedule<T>::dispatch(Task<T>*);

    template<typename T>
      friend int ticket() {
          return ++Manager::counter;
      }
    static int counter;
};

Just as with ordinary friend declarations, a friend template can be a definition only if it names an unqualified function name that is not followed by angle brackets.

A friend template can declare only primary templates and members of primary templates. Any partial specializations and explicit specializations associated with a primary template are automatically considered friends too.

12.6 Afternotes

The general concept and syntax of C++ templates have remained relatively stable since their inception in the late 1980s. Class templates and function templates were part of the initial template facility. So were type parameters and nontype parameters.

However, there were also some significant additions to the original design, mostly driven by the needs of the C++ standard library. Member templates may well be the most fundamental of those additions. Curiously, only member function templates were formally voted into the C++ standard. Member class templates became part of the standard by an editorial oversight.

Friend templates, default template arguments, and template template parameters came afterward during the standardization of C++98. The ability to declare template template parameters is sometimes called higher-order genericity. They were originally introduced to support a certain allocator model in the C++ standard library, but that allocator model was later replaced by one that does not rely on template template parameters. Later, template template parameters came close to being removed from the language because their specification had remained incomplete until very late in the standardization process for the 1998 standard. Eventually a majority of committee members voted to keep them and their specifications were completed.

Alias templates were introduced as part of the 2011 standard. Alias templates serve the same needs as the oft-requested “typedef templates” feature by making it easy to write a template that is merely a different spelling of an existing class template. The specification (N2258) that made it into the standard was authored by Gabriel Dos Reis and Bjarne Stroustrup; Mat Marcus also contributed to some of the early drafts of that proposal. Gaby also worked out the details of the variable template proposal for C++14 (N3651). Originally, the proposal only intended to support constexpr variables, but that restriction was lifted by the time it was adopted in the draft standard.

Variadic templates were driven by the needs of the C++11 standard library and the Boost libraries (see [Boost]), where C++ template libraries were using increasingly advanced (and convoluted) techniques to provide templates that accept an arbitrary number of template arguments. Doug Gregor, Jaakko J¨arvi, Gary Powell, Jens Maurer, and Jason Merrill provided the initial specification for the standard (N2242). Doug also developed the original implementation of the feature (in GNU’s GCC) while the specification was being developed, which much helped the ability to use the feature in the standard library.

Fold expressions were the work of Andrew Sutton and Richard Smith: They were added to C++17 through their paper N4191.

1 An exception since C++14 are the implicit template type parameters for a generic lambda; see Section 15.10.6 on page 309.

2 The keyword class does not imply that the substituting argument should be a class type. It could be any accessible type.

3 Template template parameters do not denote types either; however, they are distinct from nontype parameters. This oddity is historical: Template template parameters were added to the language after type parameters and nontype parameters.

4 At the time of this writing, only “pointer to object” and “pointer to function” types are permitted, which excludes types like void*. However, all compilers appear to accept void* also.

5 See Appendix B for a discussion of value categories such as rvalues and lvalues.

6 Template arguments for subsequent template parameters can still be determined by template argument deduction; see Chapter 15.

7 However, a constructor template can be a default constructor.

8 The term variadic is borrowed from C’s variadic functions, which accept a variable number of function arguments. Variadic templates also borrowed from C the use of the ellipsis to denote zero or more arguments and are intended as a type-safe replacement for C’s variadic functions for some applications.

9 This syntactic understanding of pack expansions is a useful tool, but it breaks down when the template parameter packs have length zero. Section 12.4.5 on page 207 provides more details about the interpretation of zero-length pack expansions.

10 Mixins are discussed in further detail in Section 21.3 on page 508.

11 There is a similar restriction on members of class templates and nested classes within class templates: If a member is declared with a type that does not appear to be a function type, but after instantiation the type of that member is a function type, the program is ill-formed because the semantic interpretation of the member has changed from a data member to a member function.

12 Because overloading these three special operators is unusual, this problem is fortunately rare (but subtle). The original proposal for fold expressions included empty expansion values for more common operators like + and *, which would have caused more serious problems.

13 This was the very first extension added to C++11, thanks to a proposal by William M. “Mike” Miller.