Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial ordering rules of template parameter pack in C++17

Here is an example from temp.deduct.partial.

template<class... Args>           void f(Args... args);         // #1
template<class T1, class... Args> void f(T1 a1, Args... args);  // #2
template<class T1, class T2>      void f(T1 a1, T2 a2);         // #3

f();                // calls #1
f(1, 2, 3);         // calls #2
f(1, 2);            // calls #3; non-variadic template #3 is more specialized
                    // than the variadic templates #1 and #2

Why f(1, 2, 3) calls #2?

It is easy to understand before CWG1395. #2 cannot be deduced from #1 because Args is a parameter pack and T1 is not, so #2 is more specialized than #1.

But how to understand this example after CWG1395? It seems that T1 can be deduced from Args now.

Similarly, if A was transformed from a function parameter pack, it is compared with each remaining parameter type of the parameter template.

like image 527
Pluto Avatar asked May 12 '21 10:05

Pluto


Video Answer


1 Answers

CWG1395 does not appear to change anything related to the example you cited from the standard. Keep in mind that CWG1935 was issued to allow for e.g.

    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);
    }

Prior to issue 1395, the argument pack expansion from the call print(os, rest...) could never be matched against the template parameter T of void print(ostream &os, const T &t), as function parameter packs explicitly had to be matched against template parameter packs:

If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails.

With the changes, the first print function now is allowed to be matched against the function parameter pack call and considered more specialized than the second overload by 13.10.3.5 [temp.deduct.partial] paragraph 10:

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.

Your example above however is not related to function parameter packs and thus not affected by the changes, so the rules of [temp.deduct.type]/13.10.3.6 §10 still apply.

like image 135
Jodocus Avatar answered Oct 03 '22 04:10

Jodocus