1
votes

I have a template class Foo that takes two (or more) template arguments. I want to use its type in a separate class Bar. See the following simple example, which compiles without error:

template <typename T, typename U> class Foo { };
template <typename T, typename U> class Bar { };
int main()
{
  Bar<int, char> bar; // quick example -- int & char could be any 2 types
  return 0;
}

The above is somewhat tedious, especially if Foo takes many template arguments and the programmer has to retype them all. I would like to have something like the following instead, but it does not compile:

template <typename T, typename U> class Foo { };
template <typename T, typename U> class Bar; // base
template <typename T, typename U> class Bar< Foo<T, U> > { }; // specialization
int main()
{
  typedef Foo<int, char> FooType;
  Bar<FooType> bar;
  return 0;
}
test.cpp:3:60: error: wrong number of template arguments (1, should be 2)
test.cpp:2:45: error: provided for ‘template class Bar’
test.cpp: In function ‘int main()’:
test.cpp:7:18: error: wrong number of template arguments (1, should be 2)
test.cpp:2:45: error: provided for ‘template class Bar’
test.cpp:7:23: error: invalid type in declaration before ‘;’ token

I am especially perplexed because this partial specialization idiom works fine for a single template argument; see the question titled: total class specialization for a template

Edit I realized that, at least for my purposes, I could get around this using C++11 variadic templates as follows. I still want to know why the second example doesn't work, though.

template <typename... FooTypes> class Bar;
template <typename... FooTypes> class Bar< Foo<FooTypes...> > { };
2
So, what problem? You have 1 argument for template class Bar but Bar should have 2 arguments. Also, you doesn't know syntax of partial template specilization. Read some basic book about C++.Torsten
It is not exactly clear what you are trying to achieve here. I think you need to answer the fundamental question: is Bar's functionality parameterized by Foo or is it parameterized by the choice of T and U? If the former, have you considered "template<typename F> class Bar" instead, where you might pass Foo as F? In the latter case, are you just trying to extract T and U from Foo as a convenience? This page may also be useful: cprogramming.com/tutorial/template_specialization.htmlJames Beilby

2 Answers

3
votes

Your class template Bar<T, U> takes two template arguments, but your specialization is only given one:

template <typename T, typename U> class Bar<Foo<T, U> > {};

Did you mean to have Bar take just one template argument and specialize it correspondingly?

template <typename T> class Bar;
template <typename T, typename U> class Bar<Foo<T, U> > {};

Note that a specialization can depend on a different number of template parameters but the specialization needs to get the same number of arguments. It also works the other way around: a full specialization can have no template parameter:

template <> class Bar<int> {};
2
votes

I'm a little confused about what you're trying to do in this line:

template <typename T, typename U> class Bar< Foo<T, U> > { }; // specialization

You're stating that the template requires two types, T and U, as type parameters. Foo is itself only one type though, the type created by instantiating the Foo template with those two arguments.

I see that you're expecting it to pick up and determine the T and U since you used them in both places, but that doesn't circumvent the fact that you only provided one type argument for a two type template specialization.