由操作符的友员模版函数引起的错误

       这几天在用C++写一个算法时,碰到一个关于操作符的友员模版的问题,具体错误恰好与博客园中另一位大侠的问题一样,具体问题与解决请参考http://www.cnblogs.com/autosar/中有关<关于操作符的友员模版函数重载>这篇文章。

      既然这样,就索性把模板类与友员方面的用法从C++Primer中整理了一下,仅供参考。

    

模板类的友元分3类:

                           非模板友元

                           约束(bound)模板友元,即友元的类型取决于类被实例化时的类型。

                           非约束(undound)模板友元,即友元的所有具体化都是类的每一个具体化的友元。

 

1.模板类的非模板友元函数

template<class T> class HasFriend { friend void counts();  //friend to all HaFriend instantiations   ... };

上诉声明使counts()函数成为模板所有实例化的友元。

     counts()函数不是通过对象调用的,也没有对象参数。它可以访问全局对象;可以使用全局指针访问非全局对象;可以创建自己的对象;可以访问独立于对象的模板类的静态数据成员。

 

为友元函数提供模板类参数,必须提供特定的具体化,如HasFriend<short>。

要提供模板类参数,必须指明具体化: template<class T> class HasFriend { friend void report(HasFriend<T> & ); // bound template friend   ... };

 

     也就是说,带HasFriend<int>参数的report()将成为HasFriend<int>类的友元函数。同样,带HasFriend<double>参数的report()将是report()的一个重载版本——它将是HasFriend<double>类的友元。

 

report()本省并不是模板函数,而只是使用一个模板作参数。这意味着必须为要使用的友元定义显示具体化: void report(HasFriend<short> & ) {...} //explicit specialization for short void report(HasFriend<int> & ) {...}     //explicit specialization for int

 

2.模板类的约束模板友元函数 修改前一个上面的范例,使友元函数本身成为模板。使类的每一个具体化都获得与友元匹配的具体化。包含以下三步:

首先,在类定义的前面声明每个模板函数: template <typename T> void counts(); template <typename T> void report(T &);

 

然后在函数中再次将模板声明为友元。这些语句根据类模板参数的类型声明具体化: template<class TT> class HasFriend { friend void counts<TT>();   friend void report<>(HasFriend<TT> &);   ... };

 

    上述声明中的<>指出这是模板具体化。对于report(),<>可以为空,这是因为可以从函数参数推断出模板类型参数(HasFriend<TT>)。不过,也可以使用report<HasFriend<TT> >(HasFriend<TT> &)。但counts()函数没有参数,因此必须使用模板参数句法(<TT>)来指明其具体化。还需要注意的是,TT是HasFriend类的参数类型。

 

假设声明了这样一个对象: HasFriend<int> squack;

则编译器将用int替换TT,并生成下面的类定义: class HasFriend<int> { friend void counts<int>();   friend void report<>(HasFriend<int> &);   ... }; 于是,模板具体化counts<int>()和report<HasFriend<int> >()被声明为HasFriend<int>类的友元。

 

最后,程序必须为友元提供模板定义,例如: template <typename T> void counts() { cout << HasFriend<T>::x << endl;}

template <typename T> void report(T & hf) {cout << hf.x << endl;}

 

调用时,counts()需要提供具体化参数类型。report()只需直接调用,例如: counts<int>();  //调用HasFriend<int>的友元函数 HasFriend<double> hfdb; report(hfdb);   //调用HasFriend<double>的友元函数

 

3.模板类的非约束模板友元函数     通过在类内部声明友元函数模板,可以创建非约束友元函数,即每个函数具体化都是每个类具体化的友元: template <typename T> class ManyFriend {... template <typename C,typename D> friend void show(C &,D &); };

 

在类外定义该友元: template <typename C,typename D> void show(C & c,D & d){ ... }

 

假如创建ManyFriend<int>类对象(hfi1)和ManyFriend<double>类对象(hfi2),传递给show(),那么编译器将生成如下具体化定义: void show<ManyFriend<int> &,ManyFriend<double> &>          (ManyFriend<int> & c,ManyFriend<double> & d){ ... }

转载请注明出处:http://www.cnblogs.com/Su-30MKK/archive/2012/09/23/2698591.html

     

posted on 2012-09-23 00:12  Su-30MKK  阅读(250)  评论(0编辑  收藏  举报