Template template parameter matching and deduction
13.4.4 [temp.arg.template]
Jason Merrill

Created on 2016-12-03.00:00:00 last changed 60 months ago


Date: 2016-12-03.00:00:00

Do the changes from P0522R0 regarding template template parameter matching apply to deduction? For example:

  template<class T, class U = T> class B { /* ... */ };
  template<template<class> class P, class T> void f(P<T>);

  int main()  {
    f(B<int>());       // OK?
    f(B<int,float>()); // ill-formed, T deduced to int and float

In deduction we can determine that P is more specialized than B, then substitute B into P<T>, and then compare B<T,T> to B<int,int>. This will allow deduction to succeed, whereas comparing <T> to <int,int> without this substitution would fail. I suppose this is similar to deducing a type parameter, substituting it into the type of a non-type parameter, then deducing the value of the non-type parameter

Does this make sense? Do we need more wording?

Consider also this example;

  template<typename> struct match;

  template<template<typename> class t,typename T>
  struct match<t<T> > { typedef int type; };      // #1

  template<template<typename,typename> class t,typename T0,typename T1>
  struct match<t<T0,T1> > { typedef int type; };  // #2

  template<typename,typename = void> struct other { };
  typedef match<other<void,void> >::type type;

Before this change, partial specialization #1 was not a candidate; now it is, and neither partial specialization is at least as specialized as the other, so we get an ambiguity. It seems that the consistent way to address this would be to use other during partial ordering, so we'd be comparing

  template<typename T>
  void fn (match<other<T>>); // i.e. other<T,void>
  template<typename T0, typename T1>
  void fn (match<other<T0,T1>>);

So #1 is more specialized, whereas before this change we chose #2.

Date User Action Args
2016-12-03 00:00:00admincreate