tuple这玩意实现方法就是递归方式展开函数包的完美示例。相关文章可以查看<深入应用C++11>3.2.1.1章节。
tuple的实现思想可以查看侯捷老师视频:https://www.bilibili.com/video/BV1p4411v7Dh?p=20
假如我们现在有如下源码:
tuple<int, double, char*> my_tuple = make_tuple(1,2.2,"love")
好吧来看 VS2013实现源码:
// CLASS tuple这里是前置声明
template<class... _Types>
class tuple;
template<>//这里是特化版本,为了中止继承
class tuple<>
{
//这里没有成员函数,什么都不存
}
//这里是真正普通模板类
template<class _This,//_This 就对应我们上面例子中的1对应的 int 类型
class... _Rest> //_Rest 就对应 double 和 char* 组成的一包
class tuple<_This, _Rest...>
: private tuple<_Rest...>//这里继承于自己,当然也不是自己,因为模板参数不一样
{
public:
typedef _This _This_type;
typedef tuple<_This, _Rest...> _Myt;
typedef tuple<_Rest...> _Mybase;
static const size_t _Mysize = 1 + sizeof...(_Rest);
_Tuple_val<_This> _Myfirst; // the stored element//这里存放第一个int类型的1
}
// CLASS tuple_element
template<size_t _Index, class _Tuple>
struct tuple_element;
template<class _This,class... _Rest>
struct tuple_element<0, tuple<_This, _Rest...> >
{ // select first element
typedef _This type;
typedef typename add_lvalue_reference<const _This>::type _Ctype;
typedef typename add_lvalue_reference<_This>::type _Rtype;
typedef typename add_rvalue_reference<_This>::type _RRtype;
typedef tuple<_This, _Rest...> _Ttype;
};
template<size_t _Index, class _This,class... _Rest>
struct tuple_element<_Index, tuple<_This, _Rest...> >//这里tuple也会拆包,直到_Index为0,此时我们想要取的值,为此类型tuple的成员变量。
: public tuple_element<_Index - 1, tuple<_Rest...> >//这里_Index 会递减,直到第一个模板参数为0
{ // recursive tuple_element definition
};
// FUNCTION get
template<size_t _Index, class... _Types> inline//这个_Types是 get函数的参数tuple的模板参数类型
typename tuple_element<_Index, tuple<_Types...> >::_Rtype//这里会根据_Types进行递减
get(tuple<_Types...>& _Tuple)//根据这里的_Tuple能够推导出tuple的一包参数_Types
{ // get reference to _Index element of tuple
typedef typename tuple_element<_Index, tuple<_Types...> >::_Ttype _Ttype;
return (((_Ttype&)_Tuple)._Myfirst._Val);//_Ttype是存着我们那个值的基类,强转即可
}
编译器编程可以运行期编程难多了。如果是运行期,可能会这样:get(0),而编译器是这样get<0>()。妙哉妙哉。
// CLASS _Ignore
class _Ignore
{ // class that ignores assignments
public:
_Ignore()
{ // construct
}
template<class _Ty>//任何类型变量都可以赋值给此类型变量
void operator=(const _Ty&) const
{ // do nothing
}
};
const _Ignore ignore;
// FUNCTION tie
template<class... _Types> inline
tuple<_Types&...>
tie(_Types&... _Args) _NOEXCEPT
{ // make tuple from elements
typedef tuple<_Types&...> _Ttype;
return (_Ttype(_Args...));//这里很简单就是把原tuple包赋值给现tuple包。
}
再讲讲tuple_cat实现方式:
std::tuple<int, double> my_tuple1(1, 2.2);
std::tuple<char*> my_tuple2("beijing");
std::tuple_cat(my_tuple1, my_tuple2);
template<class... _Tuples> inline
typename _Tuple_cat1<_Tuples...>::type
tuple_cat(_Tuples&&... _Tpls)
{ // concatenate tuples
typedef _Tuple_cat1<_Tuples...> _Cat1;
return (_Tuple_cat<typename _Cat1::type>(
typename _Cat1::_Kx_arg_idx(), typename _Cat1::_Ix_arg_idx(),
_STD forward_as_tuple(_STD forward<_Tuples>(_Tpls)...)));
}
template<class _Ret,
size_t... _Kx,
size_t... _Ix,
class _Ty> inline
_Ret _Tuple_cat(_Arg_idx<_Kx...>, _Arg_idx<_Ix...>, _Ty&& _Arg)
{ // concatenate tuples
cout << typeid(_Arg_idx<_Kx...>).name() << endl;//我自己添加的打印
cout << typeid(_Arg_idx<_Ix...>).name() << endl;
cout << typeid(_Ty).name() << endl;
return (_Ret(_STD get<_Kx>(_STD get<_Ix>(_STD forward<_Ty>(_Arg)))...));
}
打印结果如下:
struct std::_Arg_idx<0,1,0>//上面这个和下面_Arg_idx这个上下对应关系
struct std::_Arg_idx<0,0,1>
class std::tuple<class std::tuple<int,double> &,class std::tuple<char *> &>
先取内层get _Arg_idx的最后一个模板参数即为1,即get<1>(my_tuple1)就得到my_tuple2,然后再调用外层get的_Arg_idx的最后一个模板参数0,即get<0>(my_tuple2)就得到了“beijing",这样依次轮询三次后,得到一个模板参数包{1,2.2,"beijing"},_Ret是返回类型tuple<int,double,char*>。用_Ret强转参数包得到了最终得tuple。