Title
Partial ordering and recursive variadic inheritance
Status
cd5
Section
13.10.3.2 [temp.deduct.call]
Submitter
John Spicer

Created on 2016-05-24.00:00:00 last changed 48 months ago

Messages

Date: 2018-11-15.00:00:00

Proposed resolution (November, 2018):

Change 13.10.3.2 [temp.deduct.call] bullet 4.3 as follows:

In general, the deduction process attempts to find template argument values that will make the deduced A identical to A (after the type A is transformed as described above). However, there are three cases that allow a difference:

  • ...

  • If P is a class and P has the form simple-template-id, then the transformed A can be a derived class D of the deduced A. Likewise, if P is a pointer to a class of the form simple-template-id, the transformed A can be a pointer to a derived class D pointed to by the deduced A. However, if there is a class C that is a (direct or indirect) base class of D and derived (directly or indirectly) from a class B and that would be a valid deduced A, the deduced A cannot be B or pointer to B, respectively. [Example:

  •   template <typename... T> struct X;
      template <> struct X<> {};
      template <typename T, typename... Ts> struct X<T, Ts...> : X<Ts...> {};
      struct D : X<int> {};
    
      template <typename... T>
      int f(const X<T...>&);
      int x = f(D());  // calls f<int>, not f<>
                       // B is X<>, C is X<int>
    

    end example]

Date: 2018-03-15.00:00:00

Notes from the March, 2018 meeting:

The relevant specification is in 13.10.3.2 [temp.deduct.call] bullet 4.3 and paragraph 5, which specifies that if there is more than one possible deduced A, deduction fails. The consensus was to add wording similar to that of overload resolution preferring “nearer” base classes.

Date: 2019-02-15.00:00:00

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

The status of an example like the following is not clear:

  template <typename... T>              struct A;
  template <>                           struct A<> {};
  template <typename T, typename... Ts> struct A<T, Ts...> : A<Ts...> {};
  struct B : A<int> {};

  template <typename... T>
  void f(const A<T...>&);

  void g() {
    f(B{});
  }

This seems to be ambiguous in the current wording because A<> and A<int> both succeed in deduction. It would be reasonable to prefer the more derived specialization.

History
Date User Action Args
2020-12-15 00:00:00adminsetmessages: + msg6423
2020-12-15 00:00:00adminsetstatus: drafting -> cd5
2018-04-11 00:00:00adminsetmessages: + msg6201
2018-04-11 00:00:00adminsetstatus: open -> drafting
2016-05-24 00:00:00admincreate