http://www.cppblog.com/unixfy/archive/2011/05/27/147448.html
怎样把函数模板声明为类模板的友元
给类模板声明友元的函数模板有三种方式,分别为:
第一种方式,在模板类内部声明友元的函数模板
第二种方式,在模板类内部声明对应版本的友元函数模板实例化
需要前置声明
这种方式是最为合理的方式
第三种方式,在模板类内部直接声明友元函数,不涉及函数模板
这种情况只能在模板类内部一起把函数的定义写出来,不能在外部实现,因为外部需要类型参数,而需要类型参数就是模板了
其实这种情况相当于一般的模板类的成员函数,也就是相当于一个函数模板
第二种方式也是一个函数模板,他们保持函数的参数类型和该模板类的实例一个类型
第一种方式更为灵活,他不会要求参数类型与模板类实例是一个类型,但是一般情况下我们也是按照一个类型使用的。
1 #include < iostream >
2 using namespace std;
3
4 /// / 第一种方式,在模板类内部声明友元的函数模板
5 // template <typename T>
6 // class C
7 // {
8 // private:
9 // T m[5];
10 // public:
11 // template <typename U>
12 // friend void foo(const C<U>& T);
13 // };
14 //
15 // template <typename T>
16 // void foo(const C<T>& t)
17 // {
18 // for (int i = 0; i < 5; ++i)
19 // {
20 // cout << t.m[i] << endl;
21 // }
22 // }
23
24 // 第二种方式,在模板类内部声明对应版本的友元函数模板实例化
25 // 需要前置声明
26 // 这种方式是最为合理的方式
27 template < typename T >
28 class C;
29
30 template < typename T >
31 void foo( const C < T >& t);
32
33 template < typename T >
34 class C
35 {
36 private :
37 T m[ 5 ];
38 public :
39 friend void foo < T > ( const C < T >& t);
40 };
41
42 template < typename T >
43 void foo( const C < T >& t)
44 {
45 for ( int i = 0 ; i < 5 ; ++ i)
46 {
47 cout << t.m[i] << endl;
48 }
49 }
50
51 /// / 第三种方式,在模板类内部直接声明友元函数,不涉及函数模板
52 /// / 这种情况只能在模板类内部一起把函数的定义写出来,不能在外部实现,因为外部需要类型参数,而需要类型参数就是模板了
53 /// / 其实这种情况相当于一般的模板类的成员函数,也就是相当于一个函数模板
54 /// / 第二种方式也是一个函数模板,他们保持函数的参数类型和该模板类的实例一个类型
55 /// / 第一种方式更为灵活,他不会要求参数类型与模板类实例是一个类型,但是一般情况下我们也是按照一个类型使用的。
56 // template <typename T>
57 // class C
58 // {
59 // private:
60 // T m[5];
61 // public:
62 // friend void foo(const C<T>& t)
63 // {
64 // for (int i = 0; i < 5; ++i)
65 // {
66 // cout << (t.m[i]) << endl;
67 // }
68 // }
69 // };
70
71 int main()
72 {
73 // C<int> c;
74 C < double > c;
75 foo(c);
76 return 0 ;
77 }