Title
Partial ordering of variadic templates reconsidered
Status
c++17
Section
13.10.3.6 [temp.deduct.type]
Submitter
John Spicer

Created on 2011-09-21.00:00:00 last changed 83 months ago

Messages

Date: 2016-11-15.00:00:00

[Moved to DR at the November, 2016 meeting.]

Date: 2016-06-15.00:00:00

Proposed resolution (June, 2016):

  1. Change 13.10.3.5 [temp.deduct.partial] paragraph 8 as follows:

  2. If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails. Otherwise, using Using the resulting types P and A, the deduction is then done as described in 13.10.3.6 [temp.deduct.type]. If P is a function parameter pack, the type A of each remaining parameter type of the argument template is compared with the type P of the declarator-id of the function parameter pack. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. Similarly, if A was transformed from a function parameter pack, it is compared with each remaining parameter type of the parameter template. If deduction succeeds for a given type, the type from the argument template is considered to be at least as specialized as the type from the parameter template. [Example:...
  3. Add the following as a new paragraph following 13.10.3.5 [temp.deduct.partial] paragraph 10:

  4. Function template F is at least as specialized as function template G if, for each pair of types used to determine the ordering, the type from F is at least as specialized as the type from G. F is more specialized than G if F is at least as specialized as G and G is not at least as specialized as F.

    If, after considering the above, function template F is at least as specialized as function template G and vice-versa, and if G has a trailing paramter pack for which F does not have a corresponding parameter, and if F does not have a trailing parameter pack, then F is more specialized than G.

This resolution also resolves issue 1825.

Date: 2013-03-15.00:00:00

Additional note (March, 2013):

For another example:

  template<typename ...T> int f(T*...) {
    return 1;
  }
  template<typename T> int f(const T&) {
    return 2;
  }
  int main() {
    if (f((int*)0) != 1) {
       return 1;
    }
    return 0;
  }

This worked as expected prior to the resolution of issue 692.

Date: 2012-10-15.00:00:00

Notes from the October, 2012 meeting:

CWG agreed that the example should be accepted, handling this case as a late tiebreaker, preferring an omitted parameter over a parameter pack.

Date: 2011-09-21.00:00:00

The resolution of issue 692 (found in document N3281) made the following example ambiguous and thus ill-formed:

    template<class T>
    void print(ostream &os, const T &t) {
        os << t;
    }

    template <class T, class... Args>
    void print(ostream &os, const T &t, const Args&... rest) {
        os << t << ", ";
        print(os, rest...);
    }

    int main() {
        print(cout, 42);
        print(cout, 42, 1.23);
    }

This pattern seems fairly intuitive; is it reason to reconsider or modify the outcome of issue 692?

(See also issue 1432.)

History
Date User Action Args
2018-02-27 00:00:00adminsetmessages: + msg6173
2018-02-27 00:00:00adminsetstatus: dr -> c++17
2017-02-06 00:00:00adminsetmessages: + msg6096
2017-02-06 00:00:00adminsetstatus: drafting -> dr
2013-03-18 00:00:00adminsetmessages: + msg4260
2012-11-03 00:00:00adminsetmessages: + msg4112
2012-11-03 00:00:00adminsetstatus: open -> drafting
2011-09-21 00:00:00admincreate