Как известно, шаблоны функций не могут быть частично специализированы на С++. Когда вы концептуально пытаетесь достичь этого, есть два возможных решения, которые вы можете использовать. Одним из них является использование структур со статической функцией, необязательно обернутой с помощью функции шаблона, например:
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
здесь необязательно, вы можете, если хотите, просто использовать элемент struct static непосредственно (хотя вам придется затем явно указать все аргументы).
Другой подход - просто перегрузить функциональные шаблоны:
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";
}
Мне кажется, что второй подход предпочтительнее. Для начала он гораздо менее подробный и гораздо яснее в отношении намерения (мы пишем функции, поэтому давайте использовать функции вместо бессмысленных структур-оболочек). Кроме того, есть некоторые интересные трюки, которые вы можете играть с функциями для управления разрешением перегрузки. Например, в иерархии наследования можно использовать нетемплированные аргументы "тега" и использовать неявное преобразование для управления приоритетом функций. Вы также получаете неявные преобразования в любое время, когда вы конкретно указываете тип в перегрузке, и если вам не нравится это поведение, вы можете просто использовать enable_if в своей перегрузке, чтобы предотвратить его (возвращая вас к структуре с помощью структур).
Есть ли причины предпочесть частично специализированные структуры? Насколько общие причины? То есть который должен быть вашим "дефолтом"? Означает ли это, если вы: а) планируете самостоятельно реализовать все специализации, а b) это используется как точка настройки, где пользователи могут вводить собственное поведение?
У Herb Sutter есть знаменитое сообщение в блоге об исключении специализации шаблона функций. В нем он также рекомендует (почти ближе к концу) предпочитать частично специализированные структуры для перегруженных шаблонов функций, но он, похоже, не дает никаких конкретных причин: http://www.gotw.ca/publications/mill17.htm.
Moral # 2: Если вы пишете шаблон базы функций, предпочитайте писать его как шаблон одной функции, который никогда не должен быть специализированным или перегруженным
(выделено курсивом).