2

Given this simple example:

template<class T, class TT>
class make_it { };

template<class T>
class make_it<T, T*> { };

make_it<int>

I would expect to be able to use it both as make_it<type, type> and make_it<type> but the example template invocation at the end of the code does not compile.

When trying to compile it with GCCI get:

test-partial-spec.cpp:8:12: error: wrong number of template arguments (1, should be 2)

Same with CLang:

test-partial-spec.cpp:8:1: error: too few template arguments for class template 'make_it'

What puzzles me more is that when I take the example from here:

template<class T1, class T2, int I>
class A {};

template<class T, int I>
class A<T, T*, I> {};

A<int, 3>

It does not compile as well:
GCC:

test-partial-spec.cpp:18:9: error: wrong number of template arguments (2, should be 3)
   18 | A<int, 3>
      |         ^

CLang:

test-partial-spec.cpp:18:8: error: template argument for template type parameter must be a type
A<int, 3>
       ^

This might look like an easy question, but how do I define a partial specialization with less parameters than the generic template?

GSerg
  • 76,472
  • 17
  • 159
  • 346

1 Answers1

3

You can't make a partial specialization which takes fewer parameters than the primary template: they have to take the same amount.

Your partial specialization lets you customize the behaviour of make_if for the case where the second template argument is a pointer to the first.

If you instead want to default the second parameter to be a pointer to the first template argument, such that make_it<int> is the same as make_it<int, int*> you can do this:

template<class T, class TT = T*>
class make_it { };

Or to make it work in some corner cases, like when T is a reference:

template<class T, class TT = std::add_pointer_t<T>>
class make_it { };
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • My example is just an absolutely minimal piece of code that demonstrates the problem. It's not what I really need in my code. So no, I don't want "T*" as second parameter, it's there just to show one of possible cases. What I really need is to be able to make multiple partial specializations, like ```template class make_it { ... some code for TT=int ... }```, ```template class make_it { ... different code for TT=float ... }``` And, well, according to cppreference site I gave a link to in my question, partial references can have any number of arguments. – Andrey Zabolotnyi Apr 14 '23 at 18:43
  • @AndreyZabolotnyi if the user writes `make_it` then which of those should be selected? – TartanLlama Apr 14 '23 at 18:52
  • Partial specializations allow you to customize a given primary template for specific arguments. So that `make_it` specialization will be selected for `make_it` and `make_it` and `make_it`, whatever, as long as the second argument is `int`. The template still requires two arguments. – TartanLlama Apr 14 '23 at 19:02
  • Thank you for clarification! I was thinking about it the other way around. The arguments to partial speciailzation are not the ones in angle brackets after template<>, but the arguments to the generic template (and to the specialized class<>). So, my specialized make_it will be instantiated when I invoke make_it and when I invoke make_it it will invoke the generic template. Thank you once again. – Andrey Zabolotnyi Apr 14 '23 at 19:37