__tuple revision 232950
1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is dual licensed under the MIT and the University of Illinois Open 7// Source Licenses. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10 11#ifndef _LIBCPP___TUPLE 12#define _LIBCPP___TUPLE 13 14#include <__config> 15#include <cstddef> 16#include <type_traits> 17 18#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 19#pragma GCC system_header 20#endif 21 22#ifdef _LIBCPP_HAS_NO_VARIADICS 23 24#include <__tuple_03> 25 26#else // _LIBCPP_HAS_NO_VARIADICS 27 28_LIBCPP_BEGIN_NAMESPACE_STD 29 30template <class _Tp> class _LIBCPP_VISIBLE tuple_size; 31 32template <class _Tp> 33class _LIBCPP_VISIBLE tuple_size<const _Tp> 34 : public tuple_size<_Tp> {}; 35 36template <class _Tp> 37class _LIBCPP_VISIBLE tuple_size<volatile _Tp> 38 : public tuple_size<_Tp> {}; 39 40template <class _Tp> 41class _LIBCPP_VISIBLE tuple_size<const volatile _Tp> 42 : public tuple_size<_Tp> {}; 43 44template <size_t _Ip, class _Tp> class _LIBCPP_VISIBLE tuple_element; 45 46template <size_t _Ip, class _Tp> 47class _LIBCPP_VISIBLE tuple_element<_Ip, const _Tp> 48{ 49public: 50 typedef typename add_const<typename tuple_element<_Ip, _Tp>::type>::type type; 51}; 52 53template <size_t _Ip, class _Tp> 54class _LIBCPP_VISIBLE tuple_element<_Ip, volatile _Tp> 55{ 56public: 57 typedef typename add_volatile<typename tuple_element<_Ip, _Tp>::type>::type type; 58}; 59 60template <size_t _Ip, class _Tp> 61class _LIBCPP_VISIBLE tuple_element<_Ip, const volatile _Tp> 62{ 63public: 64 typedef typename add_cv<typename tuple_element<_Ip, _Tp>::type>::type type; 65}; 66 67template <class ..._Tp> class _LIBCPP_VISIBLE tuple; 68template <class _T1, class _T2> struct _LIBCPP_VISIBLE pair; 69template <class _Tp, size_t _Size> struct _LIBCPP_VISIBLE array; 70 71template <class _Tp> struct __tuple_like : false_type {}; 72 73template <class _Tp> struct __tuple_like<const _Tp> : public __tuple_like<_Tp> {}; 74template <class _Tp> struct __tuple_like<volatile _Tp> : public __tuple_like<_Tp> {}; 75template <class _Tp> struct __tuple_like<const volatile _Tp> : public __tuple_like<_Tp> {}; 76 77template <class... _Tp> struct __tuple_like<tuple<_Tp...> > : true_type {}; 78template <class _T1, class _T2> struct __tuple_like<pair<_T1, _T2> > : true_type {}; 79template <class _Tp, size_t _Size> struct __tuple_like<array<_Tp, _Size> > : true_type {}; 80 81template <size_t _Ip, class ..._Tp> 82typename tuple_element<_Ip, tuple<_Tp...> >::type& 83get(tuple<_Tp...>&) _NOEXCEPT; 84 85template <size_t _Ip, class ..._Tp> 86const typename tuple_element<_Ip, tuple<_Tp...> >::type& 87get(const tuple<_Tp...>&) _NOEXCEPT; 88 89template <size_t _Ip, class ..._Tp> 90typename tuple_element<_Ip, tuple<_Tp...> >::type&& 91get(tuple<_Tp...>&&) _NOEXCEPT; 92 93template <size_t _Ip, class _T1, class _T2> 94typename tuple_element<_Ip, pair<_T1, _T2> >::type& 95get(pair<_T1, _T2>&) _NOEXCEPT; 96 97template <size_t _Ip, class _T1, class _T2> 98const typename tuple_element<_Ip, pair<_T1, _T2> >::type& 99get(const pair<_T1, _T2>&) _NOEXCEPT; 100 101template <size_t _Ip, class _T1, class _T2> 102typename tuple_element<_Ip, pair<_T1, _T2> >::type&& 103get(pair<_T1, _T2>&&) _NOEXCEPT; 104 105template <size_t _Ip, class _Tp, size_t _Size> 106_Tp& 107get(array<_Tp, _Size>&) _NOEXCEPT; 108 109template <size_t _Ip, class _Tp, size_t _Size> 110const _Tp& 111get(const array<_Tp, _Size>&) _NOEXCEPT; 112 113template <size_t _Ip, class _Tp, size_t _Size> 114_Tp&& 115get(array<_Tp, _Size>&&) _NOEXCEPT; 116 117// __make_tuple_indices 118 119template <size_t...> struct __tuple_indices {}; 120 121template <size_t _Sp, class _IntTuple, size_t _Ep> 122struct __make_indices_imp; 123 124template <size_t _Sp, size_t ..._Indices, size_t _Ep> 125struct __make_indices_imp<_Sp, __tuple_indices<_Indices...>, _Ep> 126{ 127 typedef typename __make_indices_imp<_Sp+1, __tuple_indices<_Indices..., _Sp>, _Ep>::type type; 128}; 129 130template <size_t _Ep, size_t ..._Indices> 131struct __make_indices_imp<_Ep, __tuple_indices<_Indices...>, _Ep> 132{ 133 typedef __tuple_indices<_Indices...> type; 134}; 135 136template <size_t _Ep, size_t _Sp = 0> 137struct __make_tuple_indices 138{ 139 static_assert(_Sp <= _Ep, "__make_tuple_indices input error"); 140 typedef typename __make_indices_imp<_Sp, __tuple_indices<>, _Ep>::type type; 141}; 142 143// __tuple_types 144 145template <class ..._Tp> struct __tuple_types {}; 146 147template <size_t _Ip> 148class _LIBCPP_VISIBLE tuple_element<_Ip, __tuple_types<> > 149{ 150public: 151 static_assert(_Ip == 0, "tuple_element index out of range"); 152 static_assert(_Ip != 0, "tuple_element index out of range"); 153}; 154 155template <class _Hp, class ..._Tp> 156class _LIBCPP_VISIBLE tuple_element<0, __tuple_types<_Hp, _Tp...> > 157{ 158public: 159 typedef _Hp type; 160}; 161 162template <size_t _Ip, class _Hp, class ..._Tp> 163class _LIBCPP_VISIBLE tuple_element<_Ip, __tuple_types<_Hp, _Tp...> > 164{ 165public: 166 typedef typename tuple_element<_Ip-1, __tuple_types<_Tp...> >::type type; 167}; 168 169template <class ..._Tp> 170class _LIBCPP_VISIBLE tuple_size<__tuple_types<_Tp...> > 171 : public integral_constant<size_t, sizeof...(_Tp)> 172{ 173}; 174 175template <class... _Tp> struct __tuple_like<__tuple_types<_Tp...> > : true_type {}; 176 177// __make_tuple_types 178 179// __make_tuple_types<_Tuple<_Types...>, _Ep, _Sp>::type is a 180// __tuple_types<_Types...> using only those _Types in the range [_Sp, _Ep). 181// _Sp defaults to 0 and _Ep defaults to tuple_size<_Tuple>. If _Tuple is a 182// lvalue_reference type, then __tuple_types<_Types&...> is the result. 183 184template <class _TupleTypes, class _Tp, size_t _Sp, size_t _Ep> 185struct __make_tuple_types_imp; 186 187template <class ..._Types, class _Tp, size_t _Sp, size_t _Ep> 188struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Sp, _Ep> 189{ 190 typedef typename remove_reference<_Tp>::type _Tpr; 191 typedef typename __make_tuple_types_imp<__tuple_types<_Types..., 192 typename conditional<is_lvalue_reference<_Tp>::value, 193 typename tuple_element<_Sp, _Tpr>::type&, 194 typename tuple_element<_Sp, _Tpr>::type>::type>, 195 _Tp, _Sp+1, _Ep>::type type; 196}; 197 198template <class ..._Types, class _Tp, size_t _Ep> 199struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep> 200{ 201 typedef __tuple_types<_Types...> type; 202}; 203 204template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value, size_t _Sp = 0> 205struct __make_tuple_types 206{ 207 static_assert(_Sp <= _Ep, "__make_tuple_types input error"); 208 typedef typename __make_tuple_types_imp<__tuple_types<>, _Tp, _Sp, _Ep>::type type; 209}; 210 211// __tuple_convertible 212 213template <bool, class _Tp, class _Up> 214struct __tuple_convertible_imp : public false_type {}; 215 216template <class _Tp0, class ..._Tp, class _Up0, class ..._Up> 217struct __tuple_convertible_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > 218 : public integral_constant<bool, 219 is_constructible<_Up0, _Tp0>::value && 220 __tuple_convertible_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; 221 222template <> 223struct __tuple_convertible_imp<true, __tuple_types<>, __tuple_types<> > 224 : public true_type {}; 225 226template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value, 227 bool = __tuple_like<_Up>::value> 228struct __tuple_convertible 229 : public false_type {}; 230 231template <class _Tp, class _Up> 232struct __tuple_convertible<_Tp, _Up, true, true> 233 : public __tuple_convertible_imp<tuple_size<typename remove_reference<_Tp>::type>::value == 234 tuple_size<_Up>::value, 235 typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type> 236{}; 237 238// __tuple_assignable 239 240template <bool, class _Tp, class _Up> 241struct __tuple_assignable_imp : public false_type {}; 242 243template <class _Tp0, class ..._Tp, class _Up0, class ..._Up> 244struct __tuple_assignable_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > 245 : public integral_constant<bool, 246 is_assignable<_Up0&, _Tp0>::value && 247 __tuple_assignable_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; 248 249template <> 250struct __tuple_assignable_imp<true, __tuple_types<>, __tuple_types<> > 251 : public true_type {}; 252 253template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value, 254 bool = __tuple_like<_Up>::value> 255struct __tuple_assignable 256 : public false_type {}; 257 258template <class _Tp, class _Up> 259struct __tuple_assignable<_Tp, _Up, true, true> 260 : public __tuple_assignable_imp<tuple_size<typename remove_reference<_Tp>::type>::value == 261 tuple_size<_Up>::value, 262 typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type> 263{}; 264 265_LIBCPP_END_NAMESPACE_STD 266 267#endif // _LIBCPP_HAS_NO_VARIADICS 268 269#endif // _LIBCPP___TUPLE 270