學習C++模板元編程(5)

來源:互聯網
上載者:User
 

這兩周學習了《C++ TMP》第五、六章,是關於TMP的序列(容器)、迭代器和演算法。做了不少習題,其中最有意思的(也是花了我最多時間的)習題是用TMP實現二分尋找樹(Binary Search Tree)。從第五章的一道關於二分樹的習題開始。題目給出一個編譯期的二分樹資料結構,例如:
   typedef tree<                  //     double
         double                   //     /   /
       , tree<void*,int,long>     //   void* char
       , char                     //   / /
       > tree_seq;                // int long
要求實現對該二分樹的前序、中序、後序遍曆,即滿足:
   BOOST_STATIC_ASSERT(( mpl::equal<
         preorder_view<tree_seq>
       , mpl::vector<double,void*,int,long,char>
       , boost::is_same<_1,_2>
       >::value ));
 
   BOOST_STATIC_ASSERT(( mpl::equal<
         inorder_view<tree_seq>
       , mpl::vector<int,void*,long,double,char>
       , boost::is_same<_1,_2>
       >::value ));
 
   BOOST_STATIC_ASSERT(( mpl::equal<
         postorder_view<tree_seq>
       , mpl::vector<int,long,void*,char,double>
       , boost::is_same<_1,_2>
       >::value ));
其實這三種遍曆是很相似的,實現了其中一個,另兩個就可以照著寫了。所以我們先從preorder_view開始著手。當然,最開始還是要先定義tree,如下:
template <class R, class LC, class RC>
struct tree
{
    typedef tree type;
    typedef R root;
    typedef LC left;
    typedef RC right;
};
 
其中type的定義是為了滿足boost::mpl的慣例,其餘三個定義顯而易見,是為了可以方便地取出tree類的根、左子樹和右子樹。接著,我們來看看如何?preorder_view。從題目給出的測試代碼可知,preorder_view的調用結果應該是類似於mpl::vector<>的一個序列,裡面是按前序的方式對tree進行遍曆所得到的元素。所以,我乾脆就用mpl::vector<>來作為preorder_view的調用結果,先寫出主模板的初稿:
template <class T>
struct preorder_view : mpl::vector<T>
{
};
 
再針對tree<>類進行偏特化,如下:
template <class R, class LC, class RC>
struct preorder_view< tree<R, LC, RC> >
{
    typedef mpl::vector<R>s t1;
    typedef typename mpl::insert_range<t1, typename mpl::end<t1>::type,
        typename preorder_view<LC>::type >::type t2;
    typedef typename mpl::insert_range<t2, typename mpl::end<t2>::type, 
        typename preorder_view<RC>::type >::type type;
};
 
這段代碼是按照前序的方式來實現,即先訪問根項目,然後以前序方式訪問左子樹,再以前序方式訪問右子樹。這個偏特化版本與主模板一道,就可以實現前序走訪了。相似地,我們可以寫出inorder_view和postorder_view,如下:
template <class T>
struct inorder_view : mpl::vector<T>
{
};
 
template <class R, class LC, class RC>
struct inorder_view< tree<R, LC, RC> >
{
    typedef typename inorder_view<LC>::type t1;
    typedef typename mpl::insert_range<t1, typename mpl::end<t1>::type,
        mpl::vector<R> >::type t2;
    typedef typename mpl::insert_range<t2, typename mpl::end<t2>::type, 
        typename inorder_view<RC>::type >::type type;
};
 
template <class T>
struct postorder_view : mpl::vector<T>
{
};
 
template <class R, class LC, class RC>
struct postorder_view< tree<R, LC, RC> >
{
    typedef typename postorder_view<LC>::type t1;
    typedef typename mpl::insert_range<t1, typename mpl::end<t1>::type, 
        typename postorder_view<RC>::type >::type t2;
    typedef typename mpl::insert_range<t2, typename mpl::end<t2>::type,
        mpl::vector<R> >::type type;
};
 
最後是測試代碼:
int main()
{
    typedef tree< double, tree<void*,int,long>, char > tree_seq;
 
    BOOST_STATIC_ASSERT(( mpl::equal<
         preorder_view<tree_seq>::type
        , mpl::vector<double,void*,int,long,char>
        >::value ));
    
    BOOST_STATIC_ASSERT(( mpl::equal<
         inorder_view<tree_seq>::type
        , mpl::vector<int,void*,long,double,char>
        >::value ));
    
    BOOST_STATIC_ASSERT(( mpl::equal<
         postorder_view<tree_seq>::type
        , mpl::vector<int,long,void*,char,double>
        >::value ));
    
    return 0;
}
 
應該說,這個開頭還是比較容易的,不過後面就有點難度了。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.