Let\'s say I have two structs, Foo
and Bar
:
template
struct Foo{};
template
struct Bar{};
In C++14, you could not deduce T
in:
template class S, T... U, T... V>
struct match_class, S> : std::true_type{};
but in C++17, you can. The behavior you see is correct.
In C++14, since you cannot deduce T
, you need a way of explicitly providing it. So you might require the class templates themselves to indicate their non-type template parameter type:
template struct Foo { using type = int; };
template struct Bar { using type = unsigned long; };
Or have an external trait for this. And then explicitly write out everything - two class templates match if they have the same non-type template parameter and then also have the same class template, in that order:
template struct make_void { using type = void; };
template using void_t = typename make_void::type;
template
struct match_class_impl : std::false_type { };
template class S, T... U, T... V>
struct match_class_impl, S> : std::true_type{};
template
struct match_class : std::false_type { };
template
struct match_class>
: match_class_impl
{ };
This is a consequence of adding support for template auto. In C++14, [temp.deduct.type] contained:
A template type argument cannot be deduced from the type of a non-type template-argument. [Example:
template
void f(double a[10][i]); int v[10][20]; f(v); // error: argument for template-parameter T cannot be deduced -end example]
But in C++17, it now reads:
When the value of the argument corresponding to a non-type template parameter
P
that is declared with a dependent type is deduced from an expression, the template parameters in the type ofP
are deduced from the type of the value. [ Example:template
struct A { }; template struct C; template struct C> { using Q = T; }; using R = long; using R = C>::Q; // OK; T was deduced to long from the // template argument value in the type A<2> — end example ] The type of
N
in the typeT[N]
isstd::size_t
. [ Example:template
struct S; template struct S { using Q = T; }; using V = decltype(sizeof 0); using V = S ::Q; // OK; T was deduced to std::size_t from the type int[42] — end example ]