boost源码解析之tuple

tuple是Boost库里面的可变长参数的实现(现已被纳入c++11标准)。
本篇源码解析是基于boost 1.60版本源码。
源码相对路径为:"boost/tuple/tuple_basic.hpp"

首先我们来看下tuple的源码实现摘要简化版本,如下:

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6, class T7, class T8, class T9>
class tuple :
  public detail::map_tuple_to_cons<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type  //主要的实现细节
{
public:
  typedef typename
    detail::map_tuple_to_cons<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type inherited;
  typedef typename inherited::head_type head_type;
  typedef typename inherited::tail_type tail_type;
//构造函数重载,分别重载0~10个参数 tuple() {} //access_traits<T0>::parameter_type,查看定义实际为const boost::remove_cv<T>::type&,即去除cv限定符的const引用类型 //源码参见"boost/type_traits/remove_cv.hpp" tuple(typename access_traits<T0>::parameter_type t0) : inherited(t0, detail::cnull(), detail::cnull(), detail::cnull(),//detail::cnull实际为空结构null_type detail::cnull(), detail::cnull(), detail::cnull(),detail::cnull(), detail::cnull(), detail::cnull()) {} //根据上面的解释简化一下 tuple(const T0 & t0, const T1 & t1) : inherited(t0, t1, null_type(), null_type(),null_type(), null_type(), null_type(), null_type(),null_type(), null_type() ){} //此处省去N个构造函数 tuple(const T0 & t0, const T1 t1, const& T2 t2, const T3 & t3, const T4 & t4, const T5 & t5, const T6 & t6, const T7 & t7, const T8 & t8,const T9 & t9) : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) {} //... } };

从上我们即可知道tuple构造函数支持可变长度(0~10个)的参数。但是具体的实现结构map_tuple_to_cons类型,
我们还不清楚,那接着我们一起看一下。

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6, class T7, class T8, class T9>
struct map_tuple_to_cons
{
  typedef
  cons< T0,typename map_tuple_to_cons<T1, T2, T3, T4, T5,T6, T7, T8, T9, null_type>::type > type;
};

不难看出,map_tuple_to_cons是一个递归的结构。具体的实现是cons,我们来看下cons的源码摘要:

template <class HT, class TT>
struct cons {
  typedef HT head_type;//成员类型 头元素
  typedef TT tail_type;//成员类型 尾元素

  typedef typename detail::wrap_non_storeable_type<head_type>::type stored_head_type;

  stored_head_type head; //头元素
  tail_type tail; //尾元素

  //分别重载了get_head和get_tail的non-const和const的版本
  typename access_traits<stored_head_type>::non_const_type
  get_head() { return head; }
 
  typename access_traits<stored_head_type>::const_type
  get_head() const { return head; }

  typename access_traits<tail_type>::non_const_type
  get_tail() { return tail; }

  typename access_traits<tail_type>::const_type
  get_tail() const { return tail; }

  cons() : head(), tail() {}

  cons(typename access_traits<stored_head_type>::parameter_type h,
       const tail_type& t) : head (h), tail(t) {}

  template <class T1, class T2, class T3, class T4, class T5,
            class T6, class T7, class T8, class T9, class T10>
  cons( T1& t1, T2& t2, T3& t3, T4& t4, T5& t5,
        T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 )
    : head (t1),
      tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) {}
     
  //此处省去部分不关心的代码...
 
  // get member functions (non-const and const)
  template <int N>
  typename access_traits< typename element<N, cons<HT, TT> >::type >::non_const_type
  get() {
    return boost::tuples::get<N>(*this); // delegate to non-member get
  }

  template <int N>
  typename access_traits< typename element<N, cons<HT, TT> >::type >::const_type
  get() const {
    return boost::tuples::get<N>(*this); // delegate to non-member get
  }
};

另外,boost库还提供可tuple的辅助函数make_tuple,支持生成返回带0~10个参数版本的tuple,比较简单,不细讲。

下面通过代码演示一下,tuple的基本使用。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include "boost/tuple/tuple.hpp"

using namespace std;
using namespace boost;

int main()
{    
     int id = 1;
     string name="liu";
     int age = 30;
    
     tuple<int, string, int > tp( id, name,  age);
     //可以通过make_tuple函数来构造tuple
     tuple<int,string,int> tp1 = make_tuple( id, name, age);
    
     //get方法的具体实现,有兴趣的可以看下,递归获取。
     cout << tp.get<0>()  << "," << tp.get<1>()  << "," << tp.get<2>() << endl;
     cout << tp.head << endl;
    
     //验证刚才讲的递归结构
     tuple< string , int> sub_tp = tp.tail;
     cout << sub_tp.head << ","  << endl;
    
     tp.get<0>() = 2;//返回
    
     //注意此种情况下id的值不会改变,tuple构造函数第一个类型为const int &类型,见tuple源码摘要
     cout << id << "==>" << tp.get<0>() << endl;

     return 0;
}

 

posted @ 2016-03-27 21:39  chuyongliu  阅读(1531)  评论(0编辑  收藏  举报