模板類別 Rational<T> 的非成員 operator* 若為模板函式,編譯器無法從 int 或 double 推導出 T,導致隱式轉換失效。
在類別內宣告友元函式模板,使其與類別模板參數 T 綁定,實例化時自動產生對應 T 的非模板函式,支援隱式轉換。
template<typename T> class Rational;
template<typename T>
const Rational<T> doMultiply(const Rational<T>&, const Rational<T>&); // 前置宣告
template<typename T>
class Rational {
// ...
friend const Rational<T> doMultiply<T>(const Rational<T>&, const Rational<T>&);
};
template<typename T>
const Rational<T> doMultiply(const Rational<T>& lhs, const Rational<T>& rhs) {
return Rational<T>(lhs.numerator()*rhs.numerator(),
lhs.denominator()*rhs.denominator());
}
template<typename T>
const Rational<T> operator*(const Rational<T>& lhs, const Rational<T>& rhs) {
return doMultiply(lhs, rhs); // 呼叫友元實作
}
doMultiply(如上)。友元模板函式會隨類別模板具現化而自動具現化,解決參數推導與隱式轉換雙重問題。