在类模板中可以出现三种友元声明:
(1)普通非模板类或函数的友元声明,将友元关系授予明确指定的类或函数。
(2)类模板或函数模板的友元声明,授予对友元所有实例的访问权。
(3)只授予对类模板或函数模板的特定实例的访问权的友元声明。

(1)普通友元:

template<class T>

class A{

   friend void fun();

//...

};
此例中fun可访问A任意类实例中的私有和保护成员

(2)一般模板友元关系

template<class type>

class A{

  template<classT>

   friend void fun(T u);

//...

};

这时友元使用与类不同的模板形参,T可以是任意合法标志符,友元函数可以访问A类的任何类实例的数据,即不论A的形参是int,double或其他都可以。

(3)特定的模板友元关系

template <class T> void fun(T,u);//对与特定的模板友元关系,这里的声明是必须的

template<class T>

class A{

   friend voidfun<T>(T u);//这里也可以是friend void fun<char>(char u);

//...

};

此时fun只有访问类中特定实例的数据。换句话说,此时具有相同模板实参的fun函数与A类才是友元关系。即假如调用fun时其模板实参为int,则它只具有A<int>的访问权限。当然friendvoid fun<T>(Tu);中<>中的T可以是任意类型,比如int,double等

 

 

 

对类建立友元函数很容易。但是迁移到模板上却容易出现让人摸不着头脑的连接错误。
层次不够,不做分析,单纯介绍两种为类模板定义友元函数的方法

  1 封闭型

C++中模板类使用友元模板函数_数据template< typename T >
C++中模板类使用友元模板函数_数据class MyClass
C++中模板类使用友元模板函数_友元函数_03{
C++中模板类使用友元模板函数_类模板_04    friend void function( MyClass< T > &arg )
C++中模板类使用友元模板函数_访问权_05    {
C++中模板类使用友元模板函数_类模板_04        C++中模板类使用友元模板函数_访问权_07
C++中模板类使用友元模板函数_访问权_08     }
C++中模板类使用友元模板函数_友元函数_09 };  要点:友元函数定义在模板体内。

       2 开放型
C++中模板类使用友元模板函数_数据template< typename T >
C++中模板类使用友元模板函数_数据class MyClass
C++中模板类使用友元模板函数_友元函数_03{
C++中模板类使用友元模板函数_类模板_04    template< typename C >
C++中模板类使用友元模板函数_类模板_04    friend void function( MyClass< C > &arg );
C++中模板类使用友元模板函数_友元函数_09 };
C++中模板类使用友元模板函数_数据
C++中模板类使用友元模板函数_数据template< typename C >
C++中模板类使用友元模板函数_数据void function( MyClass< C > &arg )
C++中模板类使用友元模板函数_友元函数_03{
C++中模板类使用友元模板函数_类模板_04    C++中模板类使用友元模板函数_访问权_07
C++中模板类使用友元模板函数_友元函数_09 }  要点:模板体内要另建模板。 
  
  3 告诉编译器声明的设个是模板
C++中模板类使用友元模板函数_数据#include <iostream>
C++中模板类使用友元模板函数_数据using namespace std;
C++中模板类使用友元模板函数_数据
C++中模板类使用友元模板函数_数据template < typename T >
C++中模板类使用友元模板函数_数据class A
C++中模板类使用友元模板函数_友元函数_03{
C++中模板类使用友元模板函数_类模板_04    friend ostream &operator<< < T >( ostream &, const A< T > & );
C++中模板类使用友元模板函数_友元函数_09 };
C++中模板类使用友元模板函数_数据
C++中模板类使用友元模板函数_数据template < typename T >
C++中模板类使用友元模板函数_数据ostream &operator<< ( ostream &output, const A< T > &a )
C++中模板类使用友元模板函数_友元函数_03{
C++中模板类使用友元模板函数_类模板_04    output << "重载成功" << endl;
C++中模板类使用友元模板函数_类模板_04    return output;
C++中模板类使用友元模板函数_友元函数_09 }
C++中模板类使用友元模板函数_数据
C++中模板类使用友元模板函数_数据int main()
C++中模板类使用友元模板函数_友元函数_03{
C++中模板类使用友元模板函数_类模板_04    A< int > a;
C++中模板类使用友元模板函数_类模板_04    cout << a;
C++中模板类使用友元模板函数_友元函数_09 }要点:显示地在重载的运算符或者函数后面加上模板声明< T>,告诉编译器友元函数是一个类型一致的模板。

 建议:
            如果希望使用函数与模板特化的类型相对应,则使用方法3(模板显示声明)
            如果希望使用函数与模板特化的类型相独立,则使用方法2(二重模板)
            简短的内联函数使用方法1

 

参考  http://blog.sina.com.cn/s/blog_7c2c21230100svc3.html