转自:http://www.cppblog.com/zerolee/archive/2010/11/03/132344.html
类模板的模板友元函数定义有2种方式:
1. 将友元模板函数直接定义在类模板中。这种方式比较简单直接。
2. 将友元模板函数声明在类模板中,定义在类模板之外。这种方式的写法,如果不小心,通常会出现编译没问题,链接时无法解析的错误。
以下是一个简单的正确的例子:
1
#include
<
iostream
>
2 #include < vector >
3
4 template < typename T >
5 class Number;
6
7 template < typename T >
8 void print( const Number < T >& n);
9
10 template < typename T >
11 std::ostream & operator << (std::ostream & os, const Number < T >& n);
12
13 template < typename T >
14 std::istream & operator >> (std::istream & is , Number < T >& n);
15
16 template < typename T, typename T2 >
17 void printVector( const std::vector < T2 >& vt, const Number < T >& n);
18
19 template < typename T >
20 class Number {
21 public :
22 Number(T v)
23 : val(v) {}
24 ~ Number() {}
25
26 private :
27 T val;
28 public :
29 friend void print<T> ( const Number < T >& n);
30 friend std::ostream & operator << <T> (std::ostream & os, const Number < T >& n);
31 friend std::istream & operator >> <T> (std::istream & is , Number < T >& n);
32
33 friend Number < T >& operator += (Number < T >& a, const Number < T >& b)
34 {
35 a.val += b.val;
36 return a;
37 }
38 template <typename T2>
39 friend void printVector<T> ( const std::vector < T2 >& vt, const Number < T >& n);
40 template <typename T2>
41 void memFunc( const std::vector < T2 >& vt, const Number < T >& n);
42 };
43
44 template < typename T >
45 std::ostream & operator << (std::ostream & os, const Number < T >& n)
46 {
47 os << n.val << std::endl;
48 return os;
49 }
50
51 template < typename T >
52 std::istream & operator >> (std::istream & is , Number < T >& n)
53 {
54 is >> n.val;
55 return is ;
56 }
57
58 template < typename T >
59 void print < T > ( const Number < T >& n)
60 {
61 std::cout << n;
62 }
63
64 template < typename T, typename T2 >
65 void printVector( const std::vector < T2 >& vt, const Number < T >& n)
66 {
67 for (unsigned int i = 0 ; i < vt.size(); i ++ )
68 std::cout << vt.at(i) << " " ;
69 std::cout << " => " << n;
70 }
71
72 template <typename T>
73 template <typename T2>
74 void Number < T > ::memFunc( const std::vector < T2 >& vt, const Number < T >& n)
75 {
76 for (unsigned int i = 0 ; i < vt.size(); i ++ )
77 std::cout << vt.at(i) << " " ;
78 std::cout << " => " << n;
79 }
80
2 #include < vector >
3
4 template < typename T >
5 class Number;
6
7 template < typename T >
8 void print( const Number < T >& n);
9
10 template < typename T >
11 std::ostream & operator << (std::ostream & os, const Number < T >& n);
12
13 template < typename T >
14 std::istream & operator >> (std::istream & is , Number < T >& n);
15
16 template < typename T, typename T2 >
17 void printVector( const std::vector < T2 >& vt, const Number < T >& n);
18
19 template < typename T >
20 class Number {
21 public :
22 Number(T v)
23 : val(v) {}
24 ~ Number() {}
25
26 private :
27 T val;
28 public :
29 friend void print<T> ( const Number < T >& n);
30 friend std::ostream & operator << <T> (std::ostream & os, const Number < T >& n);
31 friend std::istream & operator >> <T> (std::istream & is , Number < T >& n);
32
33 friend Number < T >& operator += (Number < T >& a, const Number < T >& b)
34 {
35 a.val += b.val;
36 return a;
37 }
38 template <typename T2>
39 friend void printVector<T> ( const std::vector < T2 >& vt, const Number < T >& n);
40 template <typename T2>
41 void memFunc( const std::vector < T2 >& vt, const Number < T >& n);
42 };
43
44 template < typename T >
45 std::ostream & operator << (std::ostream & os, const Number < T >& n)
46 {
47 os << n.val << std::endl;
48 return os;
49 }
50
51 template < typename T >
52 std::istream & operator >> (std::istream & is , Number < T >& n)
53 {
54 is >> n.val;
55 return is ;
56 }
57
58 template < typename T >
59 void print < T > ( const Number < T >& n)
60 {
61 std::cout << n;
62 }
63
64 template < typename T, typename T2 >
65 void printVector( const std::vector < T2 >& vt, const Number < T >& n)
66 {
67 for (unsigned int i = 0 ; i < vt.size(); i ++ )
68 std::cout << vt.at(i) << " " ;
69 std::cout << " => " << n;
70 }
71
72 template <typename T>
73 template <typename T2>
74 void Number < T > ::memFunc( const std::vector < T2 >& vt, const Number < T >& n)
75 {
76 for (unsigned int i = 0 ; i < vt.size(); i ++ )
77 std::cout << vt.at(i) << " " ;
78 std::cout << " => " << n;
79 }
80
1) 以上代码中,operator +=被定义在类模板内部。其他3个函数先被声明(需提前声明类模板,如果模板函数的参数中含有类模板),然后在类模板中被声明为友元函数, 之后被定义在类模板体之外。
2) 请注意当模板函数被声明为类模板的友元时, 在函数名之后必须紧跟模板实参表,用来代表该友元声明指向函数模板的实例。否则友元函数会被解释为一个非模板函数,链接时无法解析。
3) 友元模板函数的模板参数类型,并不一定要求是类模板的参数类型,也可以另外声明。