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;
}