This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 112e. See for the official list.


2664. Deduction failure in CTAD for alias templates

Section:  [over.match.class.deduct]     Status: C++23     Submitter: Christof Meerwald     Date: 2022-12-05

[Accepted as a DR at the February, 2023 meeting.]

Subclause [over.match.class.deduct] paragraph 3 has an exception only for deduction failure for non-deduced contexts when deducing the return type from the defining-type-id, but not for other cases where deduction fails according to [temp.deduct.type] paragraph 2. For example,

  template <class S1, class S2> struct C {

  template<class T1> C(T1) -> C<T1, T1>;
  template<class T1, class T2> C(T1, T2) -> C<T1 *, T2>;

  template<class V1, class V2> using A = C<V1, V2>;

  C c1{""};
  A a1{""};

  C c2{"", 1};
  A a2{"", 1};

resulting in A having neither of these deduction guides. There is implementation divergence in the handling of this example.

Suggested resolution:

We could say that cases where P involves a template parameter and A is not of the same form (under [temp.deduct.type] paragraph 8) are non-deduced contexts for the purpose of these deductions. That should be enough to make it clear what happens for a2, where we'd deduce T2 = V2, and not deduce anything for T1, but wouldn't fix a1 due to the inconsistent deductions for T1; maybe this is what MSVC is doing. We could further fix a1 by allowing inconsistent deductions and treating them as if no value was deduced. Another option might be to do independent deductions for each template argument of the simple-template-id, and then try to merge the results for template arguments where deduction was successful; that'd be clearer that deduction can't fail, but would deduce less.

CWG 2023-02-08

In the example, A is the most trivial alias template imaginable; having this cause issues depending on the details of C is concerning.

Proposed resolution (approved by CWG 2023-02-09):

Change in [over.match.class.deduct] paragraph 3 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. ...