6

(Yes, the title is so weird thanks to my poor English; I hope someone can improve it.)

Answering this question, I found that this code works:

template <typename T1, typename T2> class A { };
template <template <typename...> class U> class B { };

int main()
{
    B<A> it_works;
}

..although template <typename...> class and template <typename, typename> class aren't equal.

I tried to figure out why it is possible and watch [temp.param] of N3337 standard, but I can't find anything. How is it possible?

Community
  • 1
  • 1
ikh
  • 10,119
  • 1
  • 31
  • 70
  • The same reason you can do `template void foo();` and then do `foo();`, or `foo();`, or whatever else you want. If you're looking for standard text, a lot of the stuff under Variadic Templates: *A template parameter pack is a template parameter that accepts zero or more template arguments* – chris Sep 26 '14 at 13:00
  • Oh, your comment is actually an answer >o – ikh Sep 26 '14 at 13:09
  • @ikh: Yes, and now it's a proper answer. – Mike Seymour Sep 26 '14 at 13:14

2 Answers2

5

Yes, it is possible to do so. C++ 11 14.3.3/3 specifically allows it, and provides an example.

3 A template-argument matches a template template-parameter (call it P) when each of the template parameters in the template-parameter-list of the template-argument’s corresponding class template or alias template (call it A) matches the corresponding template parameter in the template-parameter-list of P. When P’s template-parameter-list contains a template parameter pack (14.5.3), the template parameter pack will match zero or more template parameters or template parameter packs in the template-parameter-list of A with the same type and form as the template parameter pack in P (ignoring whether those template parameters are template parameter packs) [ Example:

template <class T> struct eval;

template <template <class, class...> class TT, class T1, class... Rest>
struct eval<TT<T1, Rest...>> { };

template <class T1> struct A;
template <class T1, class T2> struct B;
template <int N> struct C;
template <class T1, int N> struct D;
template <class T1, class T2, int N = 17> struct E;

eval<A<int>> eA; // OK: matches partial specialization of eval
eval<B<int, float>> eB; // OK: matches partial specialization of eval
eval<C<17>> eC; // error: C does not match TT in partial specialization
eval<D<int, 17>> eD; // error: D does not match TT in partial specialization
eval<E<int, float>> eE; // error: E does not match TT in partial specialization

—end example ]

(Emphasis mine)

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
3

[temp.arg.template] describes how template template arguments are matched with the corresponding parameter. In particular, C++11 14.3.3/3 says

When P’s template-parameter-list contains a template parameter pack, the template parameter pack will match zero or more template parameters or template parameter packs in the template-parameter-list of A with the same type and form as the template parameter pack in P

where P is the parameter (U in your example), and A the argument (A in your example). So your example, with only a parameter pack, will match a template with any number of type parameters.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Umm. I cannot decide to select your answer or Angew's answer.... but I'm finally going to accept yours due to its simplicity. (however I'm still unwilling to select *only* one of them >o<) – ikh Sep 26 '14 at 13:22