Tuple的取值过程/求长度

要求

someTuple.get<N>();  // get是模板函数

要求:N必须得是编译期可计算的常量

为什么你不能试图用变量作下标来获取tuple中的变量?

someTuple.get(N);     // N为变量-->错误

原因就在于get函数的返回值用户可以将不同形式的变量保存在tuple中,但是get函数是不能在运行期决定它的返回值的,返回值必须在编译期就决议出来。

tuple<int,long,bool>MyTuple;中有三个变量。

如果你写MyTuple.get<0>()则该get的具现化版本的返回值将被推导为int

如果你写MyTuple.get<1>()则这个get的具现化版本返回值将被推导为longget的返回值由其模板参数决定,而所有这些都在编译期。

get模板函数是怎样由它的模板参数(一个编译期整型数)来推导出其返回值的?

下面是cons<>成员get函数的源代码:

template <int N>

   typename access_traits<   //access_traits<>上面已经讲过

     typename element<N, cons<HT,TT> >::type // element<>就是那个关键的traits

>::non_const_type// 注意这个复杂的返回类型

   get() {

     return boost::tuples::get<N>(*this);  //转向全局的get<>函数

   }

注:cons<>成员get函数内部调用 boost::tuples::get<N>(*this);  //转向全局的get<>函数

请回顾我们的例子。假设我们现在写:

MyTuple.get<2>();

最外层cons<>HT=int,TT=cons<long,cons<bool,null_type>>;

而调用的get正是最外层的。所以element<N,cons<HT,TT>>::type被推导为:

   element<2,cons<int,cons<long,cons<bool,null_type>> > >::type

element<>的定义:递归定义+模板特化结束

emplate<int N, class T> // 这个int N会递减,以呈现递归的形式

   struct element

   {

   private:

     typedef typename T::tail_type Next;

                       // cons<>内部tail_typetypedefTT,请回顾上面cons<>的代码

   public:             //cons<>内部有两个关键的typedefhead_typetail_type

     typedef typename element<N-1, Next>::type type; //递归

   };

 

   template<class T>

   struct element<0,T>  //递归至N=0时,山穷水尽

   {

     typedef typename T::head_type type; // 山穷水尽时直接将head_type定义为type

   };

推导过程:

1,    element<2,cons<int,cons<long,cons<bool,null_type> >> >::type

2,    element<1,cons<long,cons<bool,null_type>> >::type;

3,     element<0,cons<bool,null_type>>::type这下编译器得采用element<>的偏特化版本了(因为第一个模板参数为0)

根据偏特化版本的定义(其中对typetypedef为:typedef typename T::head_type type;)你可以看出这实际就是:bool

类似的:N=1

typename element<1,cons<int,cons<long,cons<bool,null_type>> > >::type

ð       typename element<0,cons<long,cons<bool,null_type>> >::type

第二行编译器会决定采用element<>的偏特化版本,从而这就是long

get的比喻:

有一排人,第一个人手里拿着一块记数牌和一个盒子(记数牌上的数字表示模板参数N,盒子当然是cons<>数据容器)

比如说,你告诉第一个人你像要那个盒子里的4(第五个)元素(它深藏在第5重盒子里),他于是将记数牌上写上4,然后再减去一,并将盒子打开一层,将里面的小盒子(t.tail,也是个cons<>容器)和记数牌一并传给第二个人;

第二个人将记数牌上的3减去一,然后再剥去一层盒子,将里面的盒子以及记数牌(现在是2)传给下一个人;

下一个人做同样的工作,直到第5个人(get_class<0>)发现记数牌上为0,那么他打开盒子,将里面的head元素传给第四个,后者再传给第三个...,一直传至你手里。

为了提高效率,get函数是inline的。

length<>来获得tuple的长度(即所含元素个数)

template<class T>

   struct length {

     staticconst int value = 1 + length<typename T::tail_type>::value; //递归

};

   template<>

   struct length<null_type>{

    static const int value = 0;

};

用法

 tuple<int,long,bool>MyTuple=make_tuple(10,10,true);

  intival=10;  long lval=10; bool bval=true;

   tuple<int&,long&,bool&>MyTuple=tie(ival,lval,bval);

   ... // 这里,你修改MyTuple里的数据会直接影响到ival,lval,bval;

  tuple<int&,string&>s(1,”345”);

访问:intj=std::get<0>(s);

std::tie(1"aa"2);

类型实际是:
std::tuple<int&,string&, int&>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值