tuple
1主要代码
1.1 __empty_not_final
template <typename _Tp>
struct __is_empty_non_tuple : is_empty<_Tp> {
};
// Using EBO for elements that are tuples causes ambiguous base errors.
template <typename _El0, typename... _El>
struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type {
};
// Use the Empty Base-class Optimization for empty, non-final types.
template <typename _Tp>
using __empty_not_final = typename conditional<__is_final(_Tp), false_type, __is_empty_non_tuple<_Tp>>::type;
1.2 _Head_base
template <size_t _Idx, typename _Head, bool = __empty_not_final<_Head>::value>
struct _Head_base;
template <size_t _Idx, typename _Head>
struct _Head_base<_Idx, _Head, true> : public _Head {
constexpr _Head_base() : _Head() {
}
constexpr _Head_base(const _Head &__h) : _Head(__h) {
}
constexpr _Head_base(const _Head_base &) = default;
constexpr _Head_base(_Head_base &&) = default;
template <typename _UHead>
constexpr _Head_base(_UHead &&__h) : _Head(std::forward<_UHead>(__h)) {
}
// 省去allocator相关的内容
static constexpr _Head &_M_head(_Head_base &__b) noexcept {
return __b; }
static constexpr const _Head &_M_head(const _Head_base &__b) noexcept {
return __b; }
};
template <size_t _Idx, typename _Head>
struct _Head_base<_Idx, _Head, false> {
constexpr _Head_base() : _M_head_impl() {
}
constexpr _Head_base(const _Head &__h) : _M_head_impl(__h) {
}
constexpr _Head_base(const _Head_base &) = default;
constexpr _Head_base(_Head_base &&) = default;
template <typename _UHead>
constexpr _Head_base(_UHead &&__h) : _M_head_impl(std::forward<_UHead>(__h)) {
}
// 省去了一些allocator相关的内容
static constexpr _Head &_M_head(_Head_base &__b) noexcept {
return __b._M_head_impl; }
static constexpr const _Head &_M_head(const _Head_base &__b) noexcept {
return __b._M_head_impl; }
_Head _M_head_impl;
};
这个类是为下面的impl服务的,保存的是tuple
中模板参数类型的第一个类型数据。对于__empty_not_final
为false
的场景,模板参数_Idx
为impl的当前索引,_Head
为当前索引对应的类型,成员变量_M_head_impl
为它的实际值,即tuple
中对应索引的类型的实际值。注意到其中的_M_head
函数,返回的就是这个值。
1.3 impl
impl0
/**
* Contains the actual implementation of the @c tuple template, stored
* as a recursive inheritance hierarchy from the first element (most
* derived class) to the last (least derived class). The @c Idx
* parameter gives the 0-based index of the element stored at this
* point in the hierarchy; we use it to implement a constant-time
* get() operation.
*/
template <size_t _Idx, typename... _Elements>
struct _Tuple_impl;
_Tuple_impl
包含了对tuple
模板的真正实现,用的是递归继承的方式。_Idx
是元素的索引。结合下面的叙述,举个例子讲述一下这里面提到的“递归继承”。
// 如果我们定义了这么一个tuple
tuple<int, float, string>;
// 那么,在tuple类里面,会有这样的对impl的一个调用。
_Tuple_impl<0, int, float, string>; // 这里调用的是impl1
// 递归地,有:
_Tuple_impl<1, float, string>; // 仍然调用impl1
_Tuple_impl<2, string>; // 这里是impl2,即这个递归的基本项(basic case)
impl1
/**
* Recursive tuple implementation. Here we store the @c Head element
* and derive from a @c Tuple_impl containing the remaining elements
* (which contains the @c Tail).
*/
template <size_t _Idx, typename _Head, typename... _Tail>
struct _Tuple_impl<_Idx, _Head, _Tail...> : public _Tuple_impl<_Idx + 1, _Tail...>,
private _Head_base<_Idx, _Head> {
template <size_t, typename...>
friend struct _Tuple_impl;
typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
typedef _Head_base<_Idx, _Head> _Base;
static constexpr _Head &_M_head(_Tuple_impl &__t) noexcept {
return _Base::_M_head(__t); }
static constexpr const _Head &_M_head(const _Tuple_impl &__t) noexcept {
return _Base::_M_head(__t); }
static constexpr _Inherited &_M_tail(_Tuple_impl &__t) noexcept {
return __t; }
static constexpr const _Inherited &_M_tail(const _Tuple_impl &__t) noexcept {
return __t; }
constexpr _Tuple_impl() : _Inherited(), _Base() {
}
explicit constexpr _Tuple_impl(const _Head &__head, const _Tail &...__tail)
: _Inherited(__tail...), _Base(__head) {
}
template <typename _UHead, typename... _UTail, typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
explicit constexpr _Tuple_impl(_UHead &&__head, _UTail &&...__tail)
: _Inherited(std::forward<_UTail>(__tail)...), _Base(std::forward<_UHead>(__head)) {
}
constexpr _Tuple_impl(const _Tuple_impl &) = default;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2729. Missing SFINAE on std::pair::operator=
_Tuple_impl &operator=(const _Tuple_impl &) = delete;
constexpr _Tuple_impl(_Tuple_impl &&__in) noexcept(
__and_<is_nothrow_move_constructible<_Head>, is_nothrow_move_constructible<_Inherited>>::value)
: _Inherited(std::move(_M_tail(__in))), _Base(std::forward<_Head>(_M_head(__in))) {
}
template <typename... _UElements>
constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...> &__in)
: _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
_Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) {
}
template <typename _UHead, typename... _UTails>
constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...> &&__in)
: _Inherited(std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
_Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) {
}
// 省去一些allocator相关的东西,区别主要在内存分配上,整体逻辑相似。
template <typename... _UElements>
_GLIBCXX20_CONSTEXPR void _M_assign(const _Tuple_impl<_Idx, _UElements...> &__in) {
_M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
_M_tail(*thi