Namespaces
Variants
Actions

Class template argument deduction (CTAD) (since C++17)

From cppreference.com
< cpp‎ | language
 
 
C++ language
General topics
Flow control
Conditional execution statements
if
Iteration statements (loops)
for
range-for (C++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications (until C++17*)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const/volatile
decltype (C++11)
auto (C++11)
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
explicit (C++11)
static

Special member functions
Templates
Miscellaneous
 
 
 
 

In order to instantiate a class template, every template argument must be known, but not every template argument has to be specified. In the following contexts the compiler will deduce the template arguments from the type of the initializer:

  • any declaration that specifies initialization of a variable and variable template, whose declared type is the class template (possibly cv-qualified):
std::pair p(2, 4.5);     // deduces to std::pair<int, double> p(2, 4.5);
std::tuple t(4, 3, 2.5); // same as auto t = std::make_tuple(4, 3, 2.5);
std::less l;             // same as std::less<void> l;
template<class T>
struct A
{
    A(T, T);
};
 
auto y = new A{1, 2}; // allocated type is A<int>
auto lck = std::lock_guard(mtx);     // deduces to std::lock_guard<std::mutex>
std::copy_n(vi1, 3,
    std::back_insert_iterator(vi2)); // deduces to std::back_insert_iterator<T>,
                                     // where T is the type of the container vi2
std::for_each(vi.begin(), vi.end(),
    Foo([&](int i) {...}));          // deduces to Foo<T>,
                                     // where T is the unique lambda type
template<class T>
struct X
{
    constexpr X(T) {}
};
 
template<X x>
struct Y {};
 
Y<0> y; // OK, Y<X<int>(0)>
(since C++20)

Contents

[edit] Deduction for class templates

[edit] Implicitly-generated deduction guides

When, in a function-style cast or in a variable's declaration, the type specifier consists solely of the name of a primary class template C (i.e., there is no accompanying template argument list), candidates for deduction are formed as follows:

  • If C is defined, for each constructor (or constructor template) Ci declared in the named primary template, a fictional function template Fi, is constructed, such that all following conditions are satisfied:
  • The template parameters of Fi are the template parameters of C followed (if Ci is a constructor template) by the template parameters of Ci (default template arguments are included too).
  • The associated constraints of Fi are the conjunction of the associated constraints of C and the associated constraints of Ci.
(since C++20)
  • The parameter list of Fi is the parameter list of Ci.
  • The return type of Fi is C followed by the template parameters of the class template enclosed in <>.
  • If C is not defined or does not declare any constructors, an additional fictional function template is added, derived as above from a hypothetical constructor C().
  • In any case, an additional fictional function template derived as above from a hypothetical constructor C(C) is added, called the copy deduction candidate.
  • For each user-defined deduction guide Gi, a fictional function or function template Fi, is constructed, such that all following conditions are satisfied:
  • The parameter list of Fi is the parameter list of Gi.
  • The return type of Fi is the simple template identifier of Gi.
  • If Gi has template parameters (syntax (2)), Fi is a function template, and its template parameter list is the template parameter list of Gi. Otherwise, Fi is a function.
  • In addition, if
  • C is defined and satisfies the requirements of an aggregate type with the assumption that any dependent base class has no virtual functions or virtual base classes,
  • there are no user-defined deduction guides for C, and
  • the variable is initialized from a non-empty list of initializers arg1, arg2, ..., argn (which may use designated initializer),
an aggregate deduction candidate may be added. The parameter list of the aggregate deduction candidate is produced from the aggregate element types, as follows:
  • Let ei be the (possibly recursive) aggregate element that would be initialized from argi, where
  • brace elision is not considered for any aggregate element that has
  • if C (or its element that is itself an aggregate) has a base that is a pack expansion:
  • if the pack expansion is a trailing aggregate element, it is considered to match all remaining elements of the initializer list;
  • otherwise, the pack is considered to be empty.
  • If there is no such ei, the aggregate deduction candidate is not added.
  • Otherwise, determine the parameter list T1, T2, ..., Tn of the aggregate deduction candidate as follows:
  • If ei is an array and argi is a braced-init-list , Ti is an rvalue reference to the declared type of ei.
  • If ei is an array and argi is a string literal, Ti is an lvalue reference to the const-qualified declared type of ei.
  • Otherwise, Ti is the declared type of ei.
  • If a pack was skipped because it is a non-trailing aggregate element, an additional parameter pack of the form Pj ... is inserted in its original aggregate element position. (This will generally cause deduction to fail.)
  • If a pack is a trailing aggregate element, the trailing sequence of parameters corresponding to it is replaced by a single parameter of the form Tn ....
The aggregate deduction candidate is a fictional function template derived as above from a hypothetical constructor C(T1, T2, ..., Tn).
During template argument deduction for the aggregate deduction candidate, the number of elements in a trailing parameter pack is only deduced from the number of remaining function arguments if it is not otherwise deduced.
template<class T>
struct A
{
    T t;
 
    struct
    {
        long a, b;
    } u;
};
 
A a{1, 2, 3};
// aggregate deduction candidate:
//   template<class T>
//   A<T> F(T, long, long);
 
template<class... Args>
struct B : std::tuple<Args...>, Args... {};
 
B b{std::tuple<std::any, std::string>{},