Effective C++Item 46は、メンバー以外の関数を入れてテンプレートを定義する必要があります.

1871 ワード

本論文のsenlie原版の転載はこの住所を保留してください.
経験:class templateを作成すると、このtemplateに関連する関数が「すべてのパラメータの隠しタイプ変換」をサポートする場合.それらの関数を「class template内部のfriend関数」と定義してください.デモの例:
template<typename T>
class Rational{
public:
	Rational(const T &numerator = 0, const T &denominator = 1) // Item 20          passed by reference      。  T               。
	const T numerator() const; //Item 28      handles         。 
	const denominator() const; 
};
template<typename T>
const Rational<T> operator*(const Rational<T> &lhs, const Rational<T> &rhs){...}


Rational<int> oneHalf(1, 2);
Rational<int> result = oneHalf * 2; //error
解析:operator*は二つのRational<T>パラメータを受け入れましたが、Tとは何かを導き出すことができませんでした.
operator*の第一パラメータはRationalとして宣言されます.operator*に渡す第一実参のタイプはRationalですので、Tは必ずintです.
operator*の第二パラメータはRational<T>として宣言され、operator*に伝達される第二の参(2)のタイプはintである.コンパイラではTとは何かを導き出せませんでした.
修正1:operator*をRationalclassのfriend関数として宣言します.コンパイルに成功しました.リンクできませんでした.
template<typename>
class Rational{
public:
	friend const Rational operator*(const Rational &lhs, const Rational &rhs);
};


template<typename T>
const Rational<T> operator*(const Rational<T> &lhs, const Rational<T> &rhs){
	...
}
解析:oneHalfはRationalであり、class Rationalを詳細に表しています.Rational<int>パラメータを受け入れるoperator*も対応して詳細に化された.関数テンプレートではなく関数にします.
しかし、その詳細な関数はRationl templateで宣言されています.Rational templateの外のoperator*はその定義を詳しく化学化していません.
訂正2:operator*関数本体を宣言式に統合する
template<typename>
class Rational{
public:
	friend const Rational operator*(const Rational &lhs, const Rational &rhs){
		return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator)
	}
};