<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      厚積薄發
      海納百川,有容乃大

      我們知道在C++模板編程中如果我們特化或是偏特化某個模板類, 我們需要重寫整個模板類中的所有函數, 但是這些代碼通常是非常相似的, 甚至在某些情況下可能只有一兩個函數會不一樣,其他函數都是一樣的。在這種情況下,同時存在多份相同的代碼,對我們維護這些代碼是非常不利的, 我們最好只需要特化其中不一樣的那個函數。

      比如下面這個模板類:

       

      template<typename T, unsigned B>
      struct Base
      {
          //other function
          
      //....
          void Func(){ cout << "primary function" << endl; }
      };
      void test1()
      {
          Base<int1> a;
          a.Func();
          Base<int16> b;
          b.Func();
      }
      int main()
      {
           test1();
      }

       

       

      只有當B等于16時, Func這個函數需要特化, 但是其他函數無論什么情況下都是一樣的。

      下面是我們的一些可能解決方案:

      方法1:

       

      template<typename T>
      struct Base<T, 16>
      {
          //other function
          
      //....
          void Func(){ cout << "specialization function" << endl; }
      };

       

      點評:通過偏特化實現,需要重寫所有的類成員方法。

       

      方法2:

       

      template<typename T, unsigned B>
      struct Base
      {
          //other function
          
      //....
          void Func()
          {
              if(B == 16)
              {
                  cout << "primary function" << endl;
              }
              else
              {
                  cout << "specialization function" << endl;
              }
          }
      };

       

      點評: 通過運行時判斷, 容易理解,但是相對低效。

       

      方法3:

       

      template<typename T, unsigned B>
      struct Base
      {
          //other function
          
      //....
          void Func()
          {
      #if B!=16
                  cout << "primary function" << endl;
      #else
                  cout << "specialization function" << endl;
      #endif
          }
      };

       

      點評: 試圖通過預編譯來實現,但是這個方法是錯誤的。C++模板編譯包括預編譯,語法檢查,模板實例化等階段,在預編譯階段模板參數都還沒有實例化呢。

       

      方法4:

       

      template<typename T, unsigned B>
      struct Base
      {
          //other function
          
      //....
          template<unsigned S>
          struct FuncObj
          {
              void operator()()
              {
                  cout<<"primary function"<<endl;
              }
          };
          template<>
          struct FuncObj<16>
          {
              void operator()()
              {
                  cout<<"specialization function"<<endl;
              }
          };
          FuncObj<B> Func;
      };

       

      點評: 通過成員類以防函數的形式特化, 增加了類成員變量。

       

      方法5:

       

      template<typename T, unsigned B>
      struct Base
      {
          //other function
          
      //....
          template<unsigned N>
          void FuncImpl()
          {
              cout<<"primary function"<<endl;
          }
          template<>
          void FuncImpl<16>()
          {
              cout<<"specialization function"<<endl;
          }
          void Func()
          {
              FuncImpl<B>();
          }
      };

       

      點評:通過類成員模板函數特化來實現。

       

      方法6:

       

      template<typename T, unsigned B>
      struct Base
      {
          //other function
          
      //....
          template<unsigned N> 
          class Int2Type
          {
              enum { value = N };
          };
          template<unsigned V>
          void FuncImpl(const Int2Type<V>)
          {
              cout<<"primary function"<<endl;
          }
          void FuncImpl(const Int2Type<16>)
          {
              cout<<"specialization function"<<endl;
          }
          void Func()
          {
              FuncImpl(Int2Type<B>());
          }
      };

       

      點評: 通過將int根據值的不同轉成不同的類型,然后通過函數重載實現。

       

      方法7:

       

      namespace
      {
          template <bool,typename T,typename> struct conditional { typedef T type; };
          template <typename T,typename U> struct conditional<false,T,U> {typedef U type; };
      }
      template<class T, unsigned B>
      struct Base
      {
          //other function
          
      //....

          void Func ()
          {
              typedef typename ::conditional<B!=16,primary_t,spec_t>::type type;
              Func_impl(type());
          }
      private:
          struct primary_t { };
          struct spec_t    { };
          void Func_impl (primary_t) { std::cout << "primary function" << std::endl; }
          void Func_impl (spec_t   ) { std::cout << "specialization function" << std::endl; }
      };

       

      點評: 和方法6類似,通過函數重載實現

       

      方法8:

       namespace

       {
          template <bool,typename T = voidstruct enable_if { typedef T type; };
          template <typename T> struct enable_if<true,T> {};
      }
      template<class T, unsigned B>
      struct Base
      {
          //other function
          
      //....

          template <unsigned N>
          typename ::enable_if<16!=N>::type
              FuncImpl () { std::cout << "primary function" << std::endl; }
          template <unsigned N>
          typename ::enable_if<16==N>::type
              FuncImpl () { std::cout << "specialization function" << std::endl; }
          void Func() {
              FuncImpl<B>();
          }
      };

      點評:通過enable_if, 利用SFINAE實現。

       

      我們可以看到根據編譯時模板參數int值的不同,我們重寫模板類的某個成員函數的方法是多種多樣的。針對上面這種情況,個人其實最推薦方法2,我們沒必要把簡單的問題復雜化。

       

      下面我們考慮另外一個需求, 當模板類的某個參數是某種類型時, 我們要求特化其中的一個成員函數:

       

      template<typename T1, typename T2>
      struct Base
      {
          //other function
          
      //....
          void Func(){ cout << "primary function" << endl; }
      };
      void test2()
      {
          Base<intint> a;
          a.Func();
          Base<intstring> b;
          b.Func();
      }
      int main()
      {
          test2();
      }

       

      要求上面的模板類如果T2 是string類型, 我們要求對Func特殊重寫,其他的成員函數無論什么情況實現都是一樣的。

      有了上面的那個例子的實現經驗, 對這個問題我們解決就方便多了。

       

      方法1:

       

      template<typename T1, typename T2>
      struct Base
      {
          //other function
          
      //....
          void Func()
          {
              if(typeid(std::string) == typeid(T2))
              {
                  cout<<"specialization function"<<endl;
              }
              else
              {
                  cout << "primary function" << endl; 
              }
          }
      };

       

      點評:通過運行時類型識別(RTTI)實現,需要打開相關編譯選項,并且低效。

       

      方法2:

       

      template<typename T1, typename T2>
      struct Base
      {
          //other function
          
      //....
          template<typename T>
          void FuncImpl()
          {
              cout << "primary function" << endl; 
          }
          template<>
          void FuncImpl<string>()
          {
              cout << "specialization function" << endl; 
          }
          void Func()
          {
              FuncImpl<T2>();
          }
      };

       

      點評:通過成員函數特化實現

       

      方法3:

       

      template<typename T1, typename T2>
      struct Base
      {
          //other function
          
      //....
          template<typename T> 
          class Type2Type
          {
              typedef T type;
          };
          template<typename T>
          void FunImpl(const Type2Type<T>)
          {
              cout << "primary function" << endl; 
          }
          template<typename T>
          void FunImpl(const Type2Type<string>)
          {
              cout << "specialization function" << endl; 
          }
          void Func()
          {
              FunImpl<T2>(Type2Type<T2>());
          }
      };

       

      點評: 通過函數重載實現

       

      方法4:

       

      template<typename T>
      struct IsString
      {
          enum { value = false };
      };
      template<>
      struct IsString<string>
      {
          enum { value = true };
      };
      template<typename T1, typename T2>
      struct Base
      {
          //other function
          
      //....
          void Func()
          { 
              if(IsString<T2>::value)
              {
                  cout << "specialization function" << endl; 
              }
              else
              {
                  cout << "primary function" << endl; 
              }
          }
      };

       

      點評: 通過編譯時類型判斷實現。

       

      方法5:

       

      template<typename T3,  typename T4>
      struct must_be_same_type
      {
          enum { ret = 0 };
      };
      template<>
      struct must_be_same_type<stringstring>
      {
          enum { ret = 1 };
      };
      template < typename T1,typename T2 >
      class Base{
      public:
          //other function
          
      //....
          void Func(){
              if(must_be_same_type<T2, string>::ret)
              {
                  cout << "specialization function" << endl; 
              }
              else
              {
                  cout << "primary function" << endl; 
              }
          }
      };

       

      點評: 和方法4類似, 是不過實現方式不一樣。

       

      最后,探討下我自己遇到的問題, 我們在寫一個事件委托(delegate)類,大概如下:

       

      template<typename return_type, typename first_type, typename second_type>
      class CEvent 
      {
      public:
          //other function
          
      //....
          return_type operator()(first_type p1, second_type p2)
          {
              return_type ret = return_type();
              //...
              
      //ret = invoker(p1, p2);
              return ret;
          }
      };
      void test3()
      {
          CEvent<intintint> e1;
          e1(12);
          CEvent<voidintint> e2;
          e2(12);
      }
      int main()
      {
          test3();
      }

       

      我們可以看到,當return_type是void時, 因為沒有返回值,上面的代碼會編譯失敗,因此我們只能偏特化這種情況:

       

      template<typename first_type, typename second_type>
      class CEvent<void, first_type, second_type>
      {
      public:
          //other function
          
      //....
          void operator()(first_type p1, second_type p2)
          {
              //...
              
      //invoker(p1, p2);
              return;
          }
      };

       

      但是,我們會發現只有這個operator()函數是需要根據return_type特殊對待的,其他函數永遠都是一樣的。

      我們現在的問題就是如何只特化這個函數。

       

      首先我們會想到如下的實現方法:

       

      template<typename T>
      struct IsVoid
      {
          enum { value = false };
      };
      template<>
      struct IsVoid<void>
      {
          enum { value = true };
      };
      template<typename return_type, typename first_type, typename second_type>
      class CEvent 
      {
      public:
          other function
          ....
          return_type operator()(first_type p1, second_type p2)
          {
              if(IsVoid<return_type>::value)
              {
                  cout << "return type is void" << endl;
                  //...
                  
      //invoker(p1, p2);
              }
              else
              {
                  cout << "return type is not void" << endl;
                  return_type ret = return_type();
                  //...
                  
      //ret = invoker(p1, p2);
                  return ret;
              }
          }
      };

       

      但是我們很快會發現這種情況下if語句被編譯進去了, 所以return_type是void的情況下還是會編譯失敗。

      我們要解決的問題就是如何把這個if語句變成函數重載,于是我們想到如下實現:

       

      template<typename T>
      struct IsVoid
      {
          enum { value = false };
      };
      template<>
      struct IsVoid<void>
      {
          enum { value = true };
      };
      template<int v>
      class Int2Type
      {
          enum {value = v };
      };
      template<typename return_type, typename first_type, typename second_type>
      class CEvent 
      {
      public:
          //other function
          
      //....
          return_type InvokerImpl(first_type p1, second_type p2, Int2Type<true>)
          {
              cout << "return type is void" << endl;
              //...
              
      //invoker(p1, p2);
          }
          return_type InvokerImpl(first_type p1, second_type p2, Int2Type<false>)
          {
              cout << "return type is not void" << endl;
              return_type ret = return_type();
              //...
              
      //ret = invoker(p1, p2);
              return ret;
          }
          return_type operator()(first_type p1, second_type p2)
          {
              return InvokerImpl(p1, p2, Int2Type<IsVoid<return_type>::value>());
          }
      };

       

      上面的實現首先通過編譯時類型識別,然后再把識別后相應的bool值轉成不同類型, 最后再利用不同類型函數重載實現。

       

      最后總結下,我們可以看到,從編譯時到運行時,從面向對象到普通泛型編程再到模板元編程,C++復雜得讓人無語, 也強大得讓人無語, 而且C++語言本身是在不斷發展的(C++11), 同一問題在C++中往往有多種解決方案,這些解決方案有的簡單,有的復雜,有的高效, 也有的低效, 而我們的目標就是利用C++這把利器尋找簡單而高效的解決方案。

       

      注:本人初學C++ templates編程,如有錯誤,歡迎指正。

            參考資料:http://bbs.csdn.net/topics/390116038

                          http://bbs.csdn.net/topics/270041821

      posted on 2013-02-14 20:49  Richard Wei  閱讀(8154)  評論(7)    收藏  舉報

      主站蜘蛛池模板: 亚洲an日韩专区在线| 国色天香成人一区二区| 国精品无码一区二区三区左线| 少妇激情一区二区三区视频小说| 久久欧洲精品成av人片| 一个人在看www免费| 报价| 欧美亚洲日本国产其他| 亚洲国产美国产综合一区| 日韩精品国产二区三区| 性色av无码久久一区二区三区| 一个人看的www视频免费观看| 国产成人精彩在线视频50| 欧美成人精品手机在线| 国产真人无码作爱免费视频app| 久久国产免费观看精品3| 日本成本人片免费网站| 丰满少妇被猛烈进出69影院| 久久人人爽人人爽人人av| 国产视频最新| 免费人成视频网站在线观看18| 国产精品午夜福利片国产| 国产地址二永久伊甸园| 99久久免费精品色老| 国产在线自拍一区二区三区| 中文字幕人妻中出制服诱惑| 亚洲第一香蕉视频啪啪爽| 国产人成精品一区二区三| 美女一级毛片无遮挡内谢| A毛片终身免费观看网站| 亚洲码欧洲码一二三四五| 国产愉拍91九色国产愉拍| 国产一区二区三区av在线无码观看| 人人妻人人狠人人爽天天综合网 | 丁香色婷婷国产精品视频| 国产亚洲一在无在线观看| 国产午夜影视大全免费观看| 久久人人爽人人人人爽av| 无码h黄肉动漫在线观看| 东京热大乱系列无码| 兴城市|