Skip to content

[over.match.class.deduct] CTAD from inherited constructors handling of template parameters with default arguments #627

@antangelo

Description

@antangelo

Full name of submitter (unless configured in github; will be published with the issue): Antonio A

Reference (section label): [over.match.class.deduct]

Link to reflector thread (if any):

Issue description:

Consider the following example:

template<typename T>
struct Base {
    Base(int);
};

template<typename T = int, typename V = float>
struct Derived : public Base<T> {
    using Base<T>::Base;
};

Derived d(1);

To form deduction guides from the inherited constructors of Base for Derived, the standard has the following text on the return type:

... 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 ...

Let C represent Derived, then the template parameter list of the alias A is that of C, and the parameter list of A contains parameters with default arguments. No partial specialization's template parameter list may contain default arguments as per [temp.spec.partial.general]p9.3. Thus, this construction as it appears in the standard is invalid in this case.

Moreover, it is insufficient to strip default arguments from the parameter list of CC because it is possible to have parameters that do not appear in the base (in the above example, V) and those parameters will not be deducible in the partial specialization.

Suggested resolution:

The specialization should have the template parameter list of C, but with the parameters rewritten such that:

  1. If a parameter has a default argument, and the parameter is not in the parameter list of B, then it is substituted by its default argument.
  2. If a parameter has a default argument, and the parameter is present in the parameter list of B, then it is replaced by the same parameter, but with the default argument removed.
  3. Parameters with no default argument remain unchanged, other than being rewritten with any changes from the above.

The alias template should have the template parameter list of C, but with the parameters rewritten such that:

  1. If a parameter has a default argument, and the parameter is not in the parameter list of B, then it is substituted by its default argument.
  2. Other parameters, including both those without default arguments and those with default arguments that appear in the parameter list of B remain unchanged, other than being rewritten with any changes from the above. In this case, it is necessary to preserve the default arguments if there are any, as that information is necessary for deduction.

With this suggested resolution, the partial specialization will not have any parameters with default arguments, default arguments for parameters not in the parameter list of B are deduced up front (as they cannot be influenced by B) and default arguments for parameters in the parameter list of B retain their default argument in A, allowing them to be deduced correctly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions