模板类的约束模板友元函数:template friend functions

本来这篇博客是不打算写的,内容不是很难,对于我自己来讲,更多的是为了突出细节。

  • 所谓template friend functions,就是使友元函数本身成为模板。基本步骤:
    1,在类定义的前面声明每个模板函数。eg:template <typename T> void counts(); template <typename T> void report<>(T &);
    2,在类声明中再次将模板声明为友元。
    template <typename TT>
    class HasFriendT
    {
        ....
        friend void counts<TT>();
        friend void report<>(Testclass<TT> &)   
    };

    声明中<>指出这是模板具体化,注意模板具体化和函数具体化有点不一样。对于report,<>可以为空,因为可以从函数参数推断出模板类型参数。在声明的例子中是:HasfriendT<TT>。然而,也可以使用report<HasFriendT<TT>> 来代替 report<>
    但是counts没有参数,因此必须使用模板参数语法(<TT>)来指明其具体化。还要注意的是,TT是Testclass类的参数类型
    3,为友元提供模板定义。这里的定义只是就“泛型”TT,每个函数定义一个就行。并不需要像函数显式具体化那样为每个特定的类型通通都定义。

  • 好了,接下来看代码:
     1  #include <iostream>
     2  
     3  using std::cout;
     4  using std::endl;
     5  
     6  template <typename T> void counts();
     7  template <typename T> void report(T &); 
     8  
     9  template <typename TT> 
    10  class HasFriendT
    11  {
    12      private:
    13          TT item;
    14          static int ct; 
    15      public:
    16          HasFriendT(const TT & i) : item(i) { ct++; }
    17          ~HasFriendT() { ct--; }
    18          friend void counts<TT>();
    19          friend void report<HasFriendT<TT>>(HasFriendT<TT> &); 
    20          //note: use report<HasFriendT<TT>> not report<TT>
    21  };
    22  
    23  template <typename T>
    24  int HasFriendT<T>::ct = 0;
    25  
    26  template <typename T>
    27  void counts()
    28  {
    29      cout << "template size: " << sizeof(HasFriendT<T>) << "; ";
    30      cout << "template counts(): " << HasFriendT<T>::ct << endl;
    31  }
    32  
    33 template <typename T>
    34  void report(T & hf)
    35  {
    36      cout << hf.item << endl;
    37  }
    38  
    39  int main(void)
    40  {
    41      counts<int>();
    42      HasFriendT<int> hfi1(11);
    43      HasFriendT<int> hfi2(22);
    44      HasFriendT<double> hfi3(15.5);
    45  
    46      report(hfi1);
    47      report(hfi2);
    48      report(hfi3);
    49  
    50      cout << "counts<int>() output: \n";
    51      counts<int>();
    52      cout << "counts<double>() output: \n";
    53      counts<double>();
    54  
    55      return 0;
    56  }

     开始的时侯,在声明模板时明明counts 和 report 的<>内都是typename T(即<typename T>),我想不明白为什么在class中friend void counts<TT>() 和 friend void report<HasFriendT<TT>>(HasFriendT<TT> &) <>内的参数就不一样了呢(一个是<HasfriendT<TT>> 一个 是 <TT>)。后来仔细看了下,才发现report函数和counts函数处理的对象不一样。report处理的是item,它是类HasFrriendT的成员数据,所以它的类型是<HasFriendT<TT>>。而counts处理的是一个静态成员,对于静态类成员,可以在类声明之外使用单独的语句进行初始化,这是因为静态类是单独存储的,而不是对象的组成部分。也正如本文开头所指出那样:在countsde<>中, TT是Testclass类的参数类型。 

  • 不知到你有没有发现上面的声明中,一会用TT,一会用T。开始我也纳闷,神经兮兮的认为它们的不同是不是隐含什么细节。后来将它们全部改成TT再编译,发现没什么问题。原来这只是一个泛型的符号而已。。当然,它们也可能真的存在什么不同,但现在我还没有发现。
posted @ 2016-08-22 22:07  busui  阅读(3589)  评论(1编辑  收藏  举报