#
When resolving a placeholder for a deduced class type ([dcl.type.class.deduct]) where the template-name or splice-type-specifier designates a primary class template C, a set of functions and function templates, called the guides of C, is formed comprising:
In addition, if C is defined and its definition satisfies the conditions for an aggregate class ([dcl.init.aggr]) with the assumption that any dependent base class has no virtual functions and no virtual base classes, and the initializer is a non-empty braced-init-list or parenthesized expression-list, and there are no deduction-guides for C, the set contains an additional function template, called the aggregate deduction candidate, defined as follows.
Let
For each
If there is no such aggregate element
The aggregate deduction candidate is derived as above from a hypothetical constructor
In addition, if C is defined and inherits constructors ([namespace.udecl]) from a direct base class denoted in the base-specifier-list by a class-or-decltype B, let A be an alias template whose template parameter list is that of C and whose defining-type-id is B.
If A is a deducible template ([dcl.type.simple]), the set contains the guides of A with the return type R of each guide replaced with typename CC<R>​::​type given a class template template <typename> class CC; whose primary template is not defined and with a single partial specialization whose template parameter list is that of A and whose template argument list is a specialization of A with the template argument list of A ([temp.dep.type]) having a member typedef type designating a template specialization with the template argument list of A but with C as the template.
[Note 2: 
Equivalently, the template parameter list of the specialization is that of C, the template argument list of the specialization is B, and the member typedef names C with the template argument list of C.
— end note]
[Example 1: template <typename T> struct B { B(T); }; template <typename T> struct C : public B<T> { using B<T>::B; }; template <typename T> struct D : public B<T> {}; C c(42); / OK, deduces C<int> D d(42); / error: deduction failed, no inherited deduction guides B(int) -> B<char>; C c2(42); / OK, deduces C<char> template <typename T> struct E : public B<int> { using B<int>::B; }; E e(42); / error: deduction failed, arguments of E cannot be deduced from introduced guides template <typename T, typename U, typename V> struct F { F(T, U, V); }; template <typename T, typename U> struct G : F<U, T, int> { using G::F::F; } G g(true, 'a', 1); / OK, deduces G<char, bool> template<class T, std::size_t N> struct H { T array[N]; }; template<class T, std::size_t N> struct I { volatile T array[N]; }; template<std::size_t N> struct J { unsigned char array[N]; }; H h = { "abc" }; / OK, deduces H<char, 4> (not T = const char) I i = { "def" }; / OK, deduces I<char, 4> J j = { "ghi" }; / error: cannot bind reference to array of unsigned char to array of char in deduction — end example]
When resolving a placeholder for a deduced class type ([dcl.type.simple]) where the template-name or splice-type-specifier designates an alias template A, the defining-type-id of A must be of the form
typename
as specified in [dcl.type.simple].
The guides of A are the set of functions or function templates formed as follows.
For each function or function template f in the guides of the template named by the simple-template-id of the defining-type-id, the template arguments of the return type of f are deduced from the defining-type-id of A according to the process in [temp.deduct.type] with the exception that deduction does not fail if not all template arguments are deduced.
If deduction fails for another reason, proceed with an empty set of deduced template arguments.
Let g denote the result of substituting these deductions into f.
If substitution succeeds, form a function or function template f'' with the following properties and add it to the set of guides of A:
  • The function type of f'' is the function type of g.
  • If f is a function template, f'' is a function template whose template parameter list consists of all the template parameters of A (including their default template arguments) that appear in the above deductions or (recursively) in their default template arguments, followed by the template parameters of f that were not deduced (including their default template arguments), otherwise f'' is not a function template.
  • The associated constraints ([temp.constr.decl]) are the conjunction of the associated constraints of g and a constraint that is satisfied if and only if the arguments of A are deducible (see below) from the return type.
  • If f is a copy deduction candidate, then f'' is considered to be so as well.
  • If f was generated from a deduction-guide ([temp.deduct.guide]), then f'' is considered to be so as well.
  • The explicit-specifier of f'' is the explicit-specifier of g (if any).
The arguments of a template A are said to be deducible from a type T if, given a class template template <typename> class AA; with a single partial specialization whose template parameter list is that of A and whose template argument list is a specialization of A with the template argument list of A ([temp.dep.type]), AA<T> matches the partial specialization.
Initialization and overload resolution are performed as described in [dcl.init] and [over.match.ctor], [over.match.copy], or [over.match.list] (as appropriate for the type of initialization performed) for an object of a hypothetical class type, where the guides of the template named by the placeholder are considered to be the constructors of that class type for the purpose of forming an overload set, and the initializer is provided by the context in which class template argument deduction was performed.
The following exceptions apply:
  • The first phase in [over.match.list] (considering initializer-list constructors) is omitted if the initializer list consists of a single expression of type cv U, where U is, or is derived from, a specialization of the class template directly or indirectly named by the placeholder.
  • 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.
If the function or function template was generated from a constructor or deduction-guide that had an explicit-specifier, each such notional constructor is considered to have that same explicit-specifier.
All such notional constructors are considered to be public members of the hypothetical class type.
[Example 2: template <class T> struct A { explicit A(const T&, ..) noexcept; / #1 A(T&&, ..); / #2 }; int i; A a1 = { i, i }; / error: explicit constructor #1 selected in copy-list-initialization during deduction, / cannot deduce from non-forwarding rvalue reference in #2 A a2{i, i}; / OK, #1 deduces to A<int> and also initializes A a3{0, i}; / OK, #2 deduces to A<int> and also initializes A a4 = {0, i}; / OK, #2 deduces to A<int> and also initializes template <class T> A(const T&, const T&) -> A<T&>; / #3 template <class T> explicit A(T&&, T&&) -> A<T>; / #4 A a5 = {0, 1}; / error: explicit deduction guide #4 selected in copy-list-initialization during deduction A a6{0,1}; / OK, #4 deduces to A<int> and #2 initializes A a7 = {0, i}; / error: #3 deduces to A<int&>, #1 and #2 declare same constructor A a8{0,i}; / error: #3 deduces to A<int&>, #1 and #2 declare same constructor template <class T> struct B { template <class U> using TA = T; template <class U> B(U, TA<U>); }; B b{(int*)0, (char*)0}; / OK, deduces B<char*> template <typename T> struct S { T x; T y; }; template <typename T> struct C { S<T> s; T t; }; template <typename T> struct D { S<int> s; T t; }; C c1 = {1, 2}; / error: deduction failed C c2 = {1, 2, 3}; / error: deduction failed C c3 = {{1u, 2u}, 3}; / OK, deduces C<int> D d1 = {1, 2}; / error: deduction failed D d2 = {1, 2, 3}; / OK, braces elided, deduces D<int> template <typename T> struct E { T t; decltype(t) t2; }; E e1 = {1, 2}; / OK, deduces E<int> template <typename. T> struct Types {}; template <typename. T> struct F : Types<T..>, T.. {}; struct X {}; struct Y {}; struct Z {}; struct W { operator Y(); }; F f1 = {Types<X, Y, Z>{}, {}, {}; / OK, F<X, Y, Z> deduced F f2 = {Types<X, Y, Z>{}, X{}, Y{}; / OK, F<X, Y, Z> deduced F f3 = {Types<X, Y, Z>{}, X{}, W{}; / error: conflicting types deduced; operator Y not considered — end example]
[Example 3: template <class T, class U> struct C { C(T, U); / #1 }; template<class T, class U> C(T, U) -> C<T, std::type_identity_t<U>>; / #2 template<class V> using A = C<V *, V *>; template<std::integral W> using B = A<W>; int i{}; double d{}; A a1(&i, &i); / deduces A<int> A a2(i, i); / error: cannot deduce V * from i A a3(&i, &d); / error: #1: cannot deduce (V*, V*) from (int *, double *) / #2: cannot deduce A<V> from C<int *, double *> B b1(&i, &i); / deduces B<int> B b2(&d, &d); / error: cannot deduce B<W> from C<double *, double *>
Possible exposition-only implementation of the above procedure: / The following concept ensures a specialization of A is deduced. template <class> class AA; template <class V> class AA<A<V>> { }; template <class T> concept deduces_A = requires { sizeof(AA<T>); }; / f1 is formed from the constructor #1 of C, generating the following function template template<class T, class U> auto f1(T, U) -> C<T, U>; / Deducing arguments for C<T, U> from C<V *, V*> deduces T as V * and U as V *; / f1' is obtained by transforming f1 as described by the above procedure. template<class V> requires deduces_A<C<V *, V *> auto f1_prime(V *, V*) -> C<V *, V *>; / f2 is formed from the deduction-guide #2 of C template<class T, class U> auto f2(T, U) -> C<T, std::type_identity_t<U>>; / Deducing arguments for C<T, std​::​type_identity_t<U>> from C<V *, V*> deduces T as V *; / f2' is obtained by transforming f2 as described by the above procedure. template<class V, class U> requires deduces_A<C<V *, std::type_identity_t<U>> auto f2_prime(V *, U) -> C<V *, std::type_identity_t<U>>; / The following concept ensures a specialization of B is deduced. template <class> class BB; template <class V> class BB<B<V>> { }; template <class T> concept deduces_B = requires { sizeof(BB<T>); }; / The guides for B derived from the above f1' and f2' for A are as follows: template<std::integral W> requires deduces_A<C<W *, W *> && deduces_B<C<W *, W *> auto f1_prime_for_B(W *, W *) -> C<W *, W *>; template<std::integral W, class U> requires deduces_A<C<W *, std::type_identity_t<U>> && deduces_B<C<W *, std::type_identity_t<U>> auto f2_prime_for_B(W *, U) -> C<W *, std::type_identity_t<U>>;
— end example]

Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant