杂谈C++11一个有趣的设计——std::_Build_index_tuple
Posted 彼 方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了杂谈C++11一个有趣的设计——std::_Build_index_tuple相关的知识,希望对你有一定的参考价值。
杂谈C++11一个有趣的设计——std::_Build_index_tuple
1、源码准备
本文是基于gcc-4.9.0的源代码进行分析,std::_Build_index_tuple是C++11才加入标准的,所以低版本的gcc源码是没有这个的,建议选择4.9.0或更新的版本去学习,不同版本的gcc源码差异应该不小,但是原理和设计思想的一样的,下面给出源码下载地址
http://ftp.gnu.org/gnu/gcc
2、使用方法
std::_Build_index_tuple
是C++11新增的一个类模板,主要是为了生成一个std::_Index_tuple<…>
的结构,下面通过一个简单的例子看一下std::_Build_index_tuple
的使用方法
#include <iostream>
#include <tuple>
template<size_t... _Indexes>
void print(const std::_Index_tuple<_Indexes...>&)
{
std::initializer_list<int> indexes = {_Indexes...};
for (auto index : indexes)
std::cout << index << " ";
std::cout << std::endl;
}
int main(int argc, char* argv[])
{
print(std::_Build_index_tuple<10>::__type());
}
输出结果如下
0 1 2 3 4 5 6 7 8 9
从代码中可以看到,print
是一个可变参函数,其传入参数类型是const std::_Index_tuple<_Indexes…>&
,而我们在主函数调用时传入的是std::_Build_index_tuple<10>::__type()
,再结合最终的输出结果,我们可以知道这里std::_Build_index_tuple<10>::__type()
生成的结果是std::_Index_tuple<0, 1, 2,…, 9>
。从而可以推断出std::_Build_index_tuple
可以生成一个std::_Index_tuple<0, …, N - 1>
的结构,其中N >= 1
3、源码解析
std::_Build_index_tuple
有可能位于libstdc++-v3\\include\\std\\utility
中,也有可能位于libstdc++-v3\\include\\std\\tuple
中,源代码版本不同是有区别的
3.1、_Index_tuple解析
// Stores a tuple of indices. Used by tuple and pair, and by bind() to extract the elements in a tuple
template<size_t... _Indexes>
struct _Index_tuple
{
typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
};
先看一下_Index_tuple
的实现,内容很简单,就是计算出传入参数的个数(sizeof…(_Indexes)
的作用就是计算出可变参的数量),然后再其最后添加上这个数字,形成一个新的_Index_tuple
。下面举例说明一下,加深大家对这个的理解
例1:_Index_tuple<0, 1, 2, 3>::__next 展开之后会变为 _Index_tuple<0, 1, 2, 3, 4>
当然,你传入_Index_tuple
的参数当然可以是无规则的,示例如下
例2:_Index_tuple<3, 8, 11, 2>::__next 展开之后会变为 _Index_tuple<3, 8, 11, 2, 4>
3.2、_Build_index_tuple解析
// Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
template<size_t _Num>
struct _Build_index_tuple
{
typedef typename _Build_index_tuple<_Num - 1>::__type::__next __type;
};
template<>
struct _Build_index_tuple<0>
{
typedef _Index_tuple<> __type;
};
这个一看就是个递归模板,因为_Build_index_tuple
有个全特化形式用于结束递归。咋一看这东西有点难理解,下面就使用数学归纳法证明我们前面所提到的那个结论,即std::_Build_index_tuple = std::_Index_tuple<0, …, N - 1>
,这里要注意N >= 1
- 当
_Num
的值为1时,_Build_index_tuple<1>::__type
=_Build_index_tuple<0>::__type::__next
=_Index_tuple<>::__next
=_Index_tuple<0>
,成立 - 当
_Num
的值为2时,_Build_index_tuple<2>::__type
=_Build_index_tuple<1>::__type::__next
,
而从上面我们已经知道了_Build_index_tuple<1>::__type
=_Index_tuple<0>
,
则可将前面的等式可变为_Build_index_tuple<2>::__type
=_Index_tuple<0>::next
=_Index_tuple<0, 1>
,成立 - 假设当
_Num
的值为N(N >= 2)时,成立,即std::_Build_index_tuple
=std::_Index_tuple<0, …, N - 1>
,
当_Num
的值为N+1(N >= 2)时,_Build_index_tuple<N + 1>::__type
=_Build_index_tuple::__type::__next
,
这里将前面假设的_Build_index_tuple::__type
=_Index_tuple<0, …, N - 1>
代入,
可得_Build_index_tuple<N + 1>::__type
=_Index_tuple<0, …, N - 1>::next
=_Index_tuple<0, …, (N + 1) - 1>
,成立
从上面的证明中我们可以看到_Build_index_tuple::__type
的类型确实是_Index_tuple<0, 1, 2, …, N-1>
,它其实就是利用了模板递归展开来实现的。
4、总结
本文介绍了C++11新增的一个类模板std::_Build_index_tuple
的使用方法和实现原理,当然这玩意平时开发应该也用不上,他主要是给标准库使用的,从官方给的注释中可以看到它是给std::tuple
、std::pair
和std::bind
提供服务的,以后我也会写这几个相关的文章,到时就可以看到std::_Build_index_tuple
的具体使用场景了。
最后,如果大家觉得本文写得好的话麻烦点赞收藏关注一下谢谢,也可以关注该专栏,以后会有更多优质文章输出的。
以上是关于杂谈C++11一个有趣的设计——std::_Build_index_tuple的主要内容,如果未能解决你的问题,请参考以下文章