Я не могу вспомнить пример, и я пытался почти с тех пор, как вы спросили. Как указывает Джаганнатха , давний совет давал совет не специализировать функции, а перегрузить их или использовать класс черт (который может быть специализированным, даже частично специализированный).
Например, если вам нужно поменять местами два элемента, лучше полагаться на перегрузки (более предсказуемо и более расширяемо):
template<class T>
void f() {
T a, b;
using std::swap; // brings std::swap into scope as "fallback"
swap(a, b); // unqualified call (no "std::") so ADL kicks in
// also look at boost::swap
}
А как вы пишете своп для ваших типов:
// the cleanest way to do it for a class template:
template<class T>
struct Ex1 {
friend void swap(Ex1& a, Ex1& b) { /* do stuff */ }
};
// you can certainly place it outside of the class instead---but in the
// same namespace as the class---if you have some coding convention
// against friends (which is common, but misguided, IMHO):
struct Ex2 {};
void swap(Ex2& a, Ex2& b) { /* do stuff */ }
Оба из них позволяют Зависимый от аргумента поиск (ADL).
Другие функции, такие как stringify / str или repr (представление), могут также не быть членами и использовать преимущества ADL через перегрузку:
struct Ex3 {
friend std::string repr(Ex3 const&) { return "<Ex3 obj>"; }
};
std::string repr(bool b) { return b ? "true" : "false"; }
// possible fallback:
template<class T>
std::string repr(T const& v) {
std::ostringstream out;
out << v;
return out.str();
}
// but in this particular case, I'd remove the fallback and document that
// repr() must be overloaded appropriately before it can be used with a
// particular type; for other operations a default fallback makes sense
Если взглянуть на это иначе, было бы неплохо, если бы шаблоны функций могли служить реестром для конкретных реализаций, но из-за ограничений (в текущем C ++ не совсем точно известно, что дает C ++ 0x здесь) они не работают так же хорошо, как перегрузка или шаблоны классов для этой цели реестра.
Есть одно удобное использование, но не важно : простое определение определенных специализаций для отдельной библиотеки, возможно общей библиотеки (.so или .dll). Это удобно, потому что требует минимальных изменений в универсальном шаблоне, но не важно, потому что оно кажется мне редким (в дикой природе, и, конечно, редким в моем опыте), и разработчики все еще могут использовать либо перегрузку, либо пересылку в полностью специализированный класс Неспециализированный метод шаблона.