Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use template specializations?

I wonder why template specializations make sense?

Aren't the following things equivalent?

Template specialization:

template <typename T>
void f(T t) {
  something(t);
}

template <>
void f<int>(int t) {
  somethingelse(t);
}

Non-template function instead of specialization:

void f(int t) {
  somethingelse(t);
}

I believe these are the same because the non-template function will always be preferred.

like image 262
Sarien Avatar asked Dec 27 '22 20:12

Sarien


2 Answers

This is the answer I came up with:

It's different if the template parameter is not a parameter of the function being defined:

template <typename T>
void f() {
  T t;
  something(t);
}

template <>
void f<int>() {
  int t;
  somethingelse(t);
}

In this case defining:

void f() {
  int t;
  somethingelse(t);
}

would make all the template versions unuseable.

Maybe somebody else has better ideas. :)

like image 194
Sarien Avatar answered Jan 04 '23 23:01

Sarien


The question boils down to determining when the specialization will be used that the overload cannot. There are different situations where this is the case although they are uncommon enough, and it is simple enough to make mistakes that the general recommendation is to prefer overloads to specializations.

  • When the caller explicitly requests the use of a template. In the code example you provide if the call is f<int>(42) or even f<42>(), then the overload will not be used.

  • When you cannot provide the required overloads, or the overload cannot be resolved at the place of call. For example if the type is not one of the function arguments (it is either not present in the signature at all or only in the return type:

    template T f();

In this case, you cannot provide overloads int f(); and double f(); but you can provide as many template specializations as you need, and it will be up to the user to force the selection of one or the other. Note that this could be considered a subcase of the previous case: because the template arguments take no part in the function arguments, the user needs to provide the template arguments, so the call is explicitly to a template.

  • When you want to place special constraints on the combination of arguments and inhibit implicit conversions:

    template void f( T, T ); // Both argument must be the same type

Because template argument deduction only perform perfect matches, this template can only be used when both arguments are of the exact same type, if you add an overload void f(int,int) that overload can be used with any combination of types that are implicitly convertible to int, like f( 5, 3.0 ), but the specialization won't.

In general, for most cases, none of the cases above really apply, so an overload should be preferred.


There might be more, but those are the ones I can recall off the top of my head

like image 41
David Rodríguez - dribeas Avatar answered Jan 04 '23 22:01

David Rodríguez - dribeas