クラステンプレートに対する friend 関数の作成を単純化する。
friend 関数は、あるクラスの補助的な追加インタフェースを提供するために使われることが多い。
例えば、ストリームへの挿入演算子(<<)、ストリームからの抽出演算子(>>)、多重定義された算術的な演算子などはしばしば friend 関数である。
クラステンプレートの friend 関数を宣言することは、非テンプレートクラスに対する friend 関数を宣言することに比べて、少し複雑である。
テンプレートが含まれる場合、クラスとその friend 関数について 4 種類の関係がありうる。
1 対多： 単一の非テンプレート関数がテンプレートクラスのインスタンス全てに対して friend 関数となる。
多対 1： テンプレート関数のインスタンス全てが、単一の非テンプレートクラスに対する friend 関数となる。
1 対 1： 1組のテンプレート引数によってインスタンス化された単一のテンプレート関数が、同じ 1 組のテンプレート引数によってインスタンス化された単一のテンプレートクラスの friend 関数となる。通常の非テンプレートクラスと通常の非テンプレート friend 関数間の関係もこの分類である。
多対多： テンプレート関数のインスタンス全てがテンプレートクラスのインスタンス全ての friend 関数となる。
C++ で 1 対 1 の関係を設定するためには追加の記述が必要であるため、この 1 対 1 関係がここでの主題である。例を以下に示す。
template
class Foo {
   T value;
public:
   Foo(const T& t) value(t) {}
   friend ostream& operator<<(ostream&, const Foo&);
};
template
ostream& operator<<(ostream os, const Foo b) {
   return os << b.value;
}
挿入子(inserter)がテンプレートではないのにテンプレート引数(T)を使用しているため、上記の例は役に立たない(訳註：friend 宣言で指定されているのは非テンプレートの operator<<() であり、下で定義されている関数テンプレートの operator<<() ではない。従って、仮に関数テンプレートがインスタンス化されたとすると、private メンバへのアクセスができずエラーが発生するだろう。また、そもそも引数の型が完全に一致する場合、非テンプレート関数が優先されるため下の関数テンプレートのインスタンスは呼び出されない。従って実際には operator<<() が見つからない、というリンカエラーが発生する)。
これはメンバ関数でないために起こる問題である。
各 T に対して別々の特殊化が作成されるように operator<<() はテンプレートでなければならない。
解法の一つとして、挿入演算子のテンプレートを friend 宣言の前にクラスの外側で宣言し、friend 宣言に <> を付加することがある。
これにより、先に宣言されたテンプレートを friend にするという指定になる。
// 前方宣言
template class Foo;
template ostream& operator<<(ostream&,
                                      const Foo&);
template
class Foo {
   T value;
public:
   Foo(const T& t) : value(t) {}
   friend ostream& operator<< <>(ostream&, const Foo&);
};
template
ostream& operator<<(ostream& os, const Foo& b)
{
   return os << b.value;
}
上記解法の欠点は、非常に冗長な点である。
Dan Saks が、上記解法の冗長性を打破する別の方法を示唆した。
彼の解法は、friend 関数の生成(Making New Friends)イディオムとして知られている。
下記のように、クラステンプレートの内部で friend 関数を定義するという発想である。
template
class Foo {
   T value;
public:
   Foo(const T& t) : value(t) {}
   friend ostream& operator<<(ostream& os, const Foo& b)
   {
      return os << b.value;
   }
};
そのような friend 関数はテンプレートではないが、新しい friend 関数を「生成」するための工場(factory)としてテンプレートのようなものとなる。
新しい非テンプレート関数が Foo の特殊化ごとに生成される。
More C++ Idioms/Making New Friends
|FRIENDかんすうのせいせい]]