As we know, function templates cannot be partially specialized in C++. When you are conceptually trying to achieve this, there are two possible solutions you can use. One of them is to use structs with a static function, optionally wrapped with a template function, like so:
template <class T, class U>
struct BarHelper
{
static void BarHelp(T t, const U& u)
{
std::cerr << "bar general\n";
}
};
template <class T>
struct BarHelper<T, double>
{
static void BarHelp(T t, const double& u)
{
std::cerr << "bar specialized\n";
}
};
template <class T, class U>
void bar(T t, const U& u)
{
BarHelper<T, U>::BarHelp(t, u);
};
bar
here is optional, you can if you like just use the struct's static member directly (though you will have to then explicitly specify all arguments).
The other approach is just to overload function templates:
template <class T, class U>
void func(T t, const U& u)
{
std::cerr << "func general\n";
}
template <class T>
void func(T t, const double& u)
{
std::cerr << "func specialized\n";
}
To me, it seems like the second approach is preferable. For starters it is much less verbose, and far clearer with regards to intent (we're writing functions, so let's use functions instead of pointless wrapper structs). Also, there are some nice tricks you can play with functions to control overload resolution. For instance, you can have non-templated "tag" arguments in an inheritance hierarchy, and use implicit conversion to control priority of functions. You also get implicit conversions anytime you concretely specify a type in an overload, and if you don't like that behavior you can just use enable_if on your overload to prevent it (bringing you back to par with structs).
Are there reasons to prefer the partially specialized structs? How general are these reasons? I.e. which should be your "default"? Does this differ if you: a) plan to implement all specializations yourself, versus b) this is used as a customization point where users can inject their own behavior?
Herb Sutter has a famous blog post about avoiding function template specialization. In it, he also recommends (right near the end) preferring partially specialized structs to overloaded function templates, but he doesn't seem to give any concrete reasons: http://www.gotw.ca/publications/mill17.htm.
Moral #2: If you're writing a function base template, prefer to write it as a single function template that should never be specialized or overloaded
(emphasis added).