I read C++ Primer, and it says function template specialization is an advanced topic, but I am totally lost. Can anybody offer an example why function template specialization is important and necessary?
Why don't function templates support partial specialization while class templates do? What's the underlying logic?
I cannot think of an example, and I've been trying nearly since you asked. As pointed out by Jagannath, it's been long-standing advice not to specialize functions, but instead overload them or use a traits class (which can be specialized, even partially specialized).
For example, if you need to swap two items, then relying on overloads is better (more predictable and more extensible):
And how you write a swap for your types:
Both of which allow Argument Dependent Lookup (ADL).
Other functions, such as a stringify/str or a repr (representation) can similarly be non-members and take advantage of ADL through overloading:
To look at it another way, it would be nice if function templates could serve as a registry for specific implementations, but due to limits (in current C++, not sure exactly what C++0x brings here) they don't work as well as either overloading or class templates for that registry purpose.
There is one use that is convenient but not important: easily defining certain specializations to be in a separate library, possibly a shared library (.so or .dll). This is convenient because it requires minimal changes to the generic template, but not important because it seems rare to me (in the wild, and certainly is rare in my experience) and implementors can still use either overloading or forwarding to a fully-specialized class template's unspecialized method.
Your question of why functions do not support partial specialization can be answered here. The code below shows how to implement the different specializations.
To illustrate why function template specialization is important, consider the
std::swap
template function. By default,std::swap(x, y)
essentially does:but this can be inefficient since it involves creating an extra copy of
x
and could do additional copying in the assignments. This is especially bad ifx
is large (for example, if it's astd::vector
with many elements). Additionally, each of the above lines could fail and throw exceptions, potentially leavingx
andy
in bad, inconsistent states.To address this, many classes provide their own
swap
methods (includingstd::vector
) that instead swap the pointers to their internal data. This is more efficient and can be guaranteed to never fail.But now you have a case where you can use
std::swap(x, y)
on some types but need to callx.swap(y)
on other types. This is confusing, and it's bad for templates since they wouldn't be able to swap two objects in a generic, consistent way.But
std::swap
can be specialized so that it callsx.swap(y)
when called on specific types. That means you then can usestd::swap
everywhere and (hopefully) expect it to be well-behaved.Basically the idea is that you can write templates that behave in a generic way for the general case, but can still handle special cases. One example of where specialization is used is in
std::vector
.std::vector<bool>
is a specialization that packs thebool
elements such that they only use one bit per element, not one byte.std::vector<T>
works like a normal dynamic array for all other types.The more advanced use for specialization is metaprogramming. For example, here's an example (from Wikipedia) of how to use template specialization to compute factorials at compile time.