我想不出一个例子,自从你问起我就一直在尝试。正如Jagannath 所指出的,long-standing advice 不是专门化函数,而是重载它们或使用特征类(可以专门化,甚至部分专门化)。
例如,如果你需要交换两个项目,那么依赖重载会更好(更可预测和更可扩展):
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 */ }
两者都允许Argument Dependent Lookup (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)。这很方便,因为它需要对通用模板进行最少的更改,但并不重要,因为它对我来说似乎很少见(在野外,而且在我的经验中当然很少见)并且实现者仍然可以使用重载或转发到完全专业化的类模板的非特化方法。