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 23 _LIBCPP_BEGIN_NAMESPACE_STD 24 25 template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size; 26 27 template <class _Tp> 28 class _LIBCPP_TYPE_VIS_ONLY tuple_size<const _Tp> 29 : public tuple_size<_Tp> {}; 30 31 template <class _Tp> 32 class _LIBCPP_TYPE_VIS_ONLY tuple_size<volatile _Tp> 33 : public tuple_size<_Tp> {}; 34 35 template <class _Tp> 36 class _LIBCPP_TYPE_VIS_ONLY tuple_size<const volatile _Tp> 37 : public tuple_size<_Tp> {}; 38 39 template <size_t _Ip, class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_element; 40 41 template <size_t _Ip, class _Tp> 42 class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, const _Tp> 43 { 44 public: 45 typedef typename add_const<typename tuple_element<_Ip, _Tp>::type>::type type; 46 }; 47 48 template <size_t _Ip, class _Tp> 49 class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, volatile _Tp> 50 { 51 public: 52 typedef typename add_volatile<typename tuple_element<_Ip, _Tp>::type>::type type; 53 }; 54 55 template <size_t _Ip, class _Tp> 56 class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, const volatile _Tp> 57 { 58 public: 59 typedef typename add_cv<typename tuple_element<_Ip, _Tp>::type>::type type; 60 }; 61 62 template <class _Tp> struct __tuple_like : false_type {}; 63 64 template <class _Tp> struct __tuple_like<const _Tp> : public __tuple_like<_Tp> {}; 65 template <class _Tp> struct __tuple_like<volatile _Tp> : public __tuple_like<_Tp> {}; 66 template <class _Tp> struct __tuple_like<const volatile _Tp> : public __tuple_like<_Tp> {}; 67 68 // tuple specializations 69 70 #if !defined(_LIBCPP_HAS_NO_VARIADICS) 71 template <class ..._Tp> class _LIBCPP_TYPE_VIS_ONLY tuple; 72 73 template <class... _Tp> struct __tuple_like<tuple<_Tp...> > : true_type {}; 74 75 template <size_t _Ip, class ..._Tp> 76 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 77 typename tuple_element<_Ip, tuple<_Tp...> >::type& 78 get(tuple<_Tp...>&) _NOEXCEPT; 79 80 template <size_t _Ip, class ..._Tp> 81 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 82 const typename tuple_element<_Ip, tuple<_Tp...> >::type& 83 get(const tuple<_Tp...>&) _NOEXCEPT; 84 85 template <size_t _Ip, class ..._Tp> 86 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 87 typename tuple_element<_Ip, tuple<_Tp...> >::type&& 88 get(tuple<_Tp...>&&) _NOEXCEPT; 89 #endif 90 91 // pair specializations 92 93 template <class _T1, class _T2> struct _LIBCPP_TYPE_VIS_ONLY pair; 94 95 template <class _T1, class _T2> struct __tuple_like<pair<_T1, _T2> > : true_type {}; 96 97 template <size_t _Ip, class _T1, class _T2> 98 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 99 typename tuple_element<_Ip, pair<_T1, _T2> >::type& 100 get(pair<_T1, _T2>&) _NOEXCEPT; 101 102 template <size_t _Ip, class _T1, class _T2> 103 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 104 const typename tuple_element<_Ip, pair<_T1, _T2> >::type& 105 get(const pair<_T1, _T2>&) _NOEXCEPT; 106 107 #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) 108 template <size_t _Ip, class _T1, class _T2> 109 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 110 typename tuple_element<_Ip, pair<_T1, _T2> >::type&& 111 get(pair<_T1, _T2>&&) _NOEXCEPT; 112 #endif 113 114 // array specializations 115 116 template <class _Tp, size_t _Size> struct _LIBCPP_TYPE_VIS_ONLY array; 117 118 template <class _Tp, size_t _Size> struct __tuple_like<array<_Tp, _Size> > : true_type {}; 119 120 template <size_t _Ip, class _Tp, size_t _Size> 121 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 122 _Tp& 123 get(array<_Tp, _Size>&) _NOEXCEPT; 124 125 template <size_t _Ip, class _Tp, size_t _Size> 126 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 127 const _Tp& 128 get(const array<_Tp, _Size>&) _NOEXCEPT; 129 130 #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) 131 template <size_t _Ip, class _Tp, size_t _Size> 132 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 133 _Tp&& 134 get(array<_Tp, _Size>&&) _NOEXCEPT; 135 #endif 136 137 #if !defined(_LIBCPP_HAS_NO_VARIADICS) 138 139 // __lazy_and 140 141 template <bool _Last, class ..._Preds> 142 struct __lazy_and_impl; 143 144 template <class ..._Preds> 145 struct __lazy_and_impl<false, _Preds...> : false_type {}; 146 147 template <> 148 struct __lazy_and_impl<true> : true_type {}; 149 150 template <class _Pred> 151 struct __lazy_and_impl<true, _Pred> : integral_constant<bool, _Pred::type::value> {}; 152 153 template <class _Hp, class ..._Tp> 154 struct __lazy_and_impl<true, _Hp, _Tp...> : __lazy_and_impl<_Hp::type::value, _Tp...> {}; 155 156 template <class _P1, class ..._Pr> 157 struct __lazy_and : __lazy_and_impl<_P1::type::value, _Pr...> {}; 158 159 // __lazy_not 160 161 template <class _Pred> 162 struct __lazy_not : integral_constant<bool, !_Pred::type::value> {}; 163 164 // __make_tuple_indices 165 166 template <size_t...> struct __tuple_indices {}; 167 168 template <size_t _Sp, class _IntTuple, size_t _Ep> 169 struct __make_indices_imp; 170 171 template <size_t _Sp, size_t ..._Indices, size_t _Ep> 172 struct __make_indices_imp<_Sp, __tuple_indices<_Indices...>, _Ep> 173 { 174 typedef typename __make_indices_imp<_Sp+1, __tuple_indices<_Indices..., _Sp>, _Ep>::type type; 175 }; 176 177 template <size_t _Ep, size_t ..._Indices> 178 struct __make_indices_imp<_Ep, __tuple_indices<_Indices...>, _Ep> 179 { 180 typedef __tuple_indices<_Indices...> type; 181 }; 182 183 template <size_t _Ep, size_t _Sp = 0> 184 struct __make_tuple_indices 185 { 186 static_assert(_Sp <= _Ep, "__make_tuple_indices input error"); 187 typedef typename __make_indices_imp<_Sp, __tuple_indices<>, _Ep>::type type; 188 }; 189 190 // __tuple_types 191 192 template <class ..._Tp> struct __tuple_types {}; 193 194 template <size_t _Ip> 195 class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, __tuple_types<> > 196 { 197 public: 198 static_assert(_Ip == 0, "tuple_element index out of range"); 199 static_assert(_Ip != 0, "tuple_element index out of range"); 200 }; 201 202 template <class _Hp, class ..._Tp> 203 class _LIBCPP_TYPE_VIS_ONLY tuple_element<0, __tuple_types<_Hp, _Tp...> > 204 { 205 public: 206 typedef _Hp type; 207 }; 208 209 template <size_t _Ip, class _Hp, class ..._Tp> 210 class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, __tuple_types<_Hp, _Tp...> > 211 { 212 public: 213 typedef typename tuple_element<_Ip-1, __tuple_types<_Tp...> >::type type; 214 }; 215 216 template <class ..._Tp> 217 class _LIBCPP_TYPE_VIS_ONLY tuple_size<__tuple_types<_Tp...> > 218 : public integral_constant<size_t, sizeof...(_Tp)> 219 { 220 }; 221 222 template <class... _Tp> struct __tuple_like<__tuple_types<_Tp...> > : true_type {}; 223 224 // __make_tuple_types 225 226 // __make_tuple_types<_Tuple<_Types...>, _Ep, _Sp>::type is a 227 // __tuple_types<_Types...> using only those _Types in the range [_Sp, _Ep). 228 // _Sp defaults to 0 and _Ep defaults to tuple_size<_Tuple>. If _Tuple is a 229 // lvalue_reference type, then __tuple_types<_Types&...> is the result. 230 231 template <class _TupleTypes, class _Tp, size_t _Sp, size_t _Ep> 232 struct __make_tuple_types_imp; 233 234 template <class ..._Types, class _Tp, size_t _Sp, size_t _Ep> 235 struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Sp, _Ep> 236 { 237 typedef typename remove_reference<_Tp>::type _Tpr; 238 typedef typename __make_tuple_types_imp<__tuple_types<_Types..., 239 typename conditional<is_lvalue_reference<_Tp>::value, 240 typename tuple_element<_Sp, _Tpr>::type&, 241 typename tuple_element<_Sp, _Tpr>::type>::type>, 242 _Tp, _Sp+1, _Ep>::type type; 243 }; 244 245 template <class ..._Types, class _Tp, size_t _Ep> 246 struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep> 247 { 248 typedef __tuple_types<_Types...> type; 249 }; 250 251 template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value, size_t _Sp = 0> 252 struct __make_tuple_types 253 { 254 static_assert(_Sp <= _Ep, "__make_tuple_types input error"); 255 typedef typename __make_tuple_types_imp<__tuple_types<>, _Tp, _Sp, _Ep>::type type; 256 }; 257 258 // __tuple_convertible 259 260 template <class, class> 261 struct __tuple_convertible_imp : public false_type {}; 262 263 template <class _Tp0, class ..._Tp, class _Up0, class ..._Up> 264 struct __tuple_convertible_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > 265 : public integral_constant<bool, 266 is_convertible<_Tp0, _Up0>::value && 267 __tuple_convertible_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; 268 269 template <> 270 struct __tuple_convertible_imp<__tuple_types<>, __tuple_types<> > 271 : public true_type {}; 272 273 template <bool, class, class> 274 struct __tuple_convertible_apply : public false_type {}; 275 276 template <class _Tp, class _Up> 277 struct __tuple_convertible_apply<true, _Tp, _Up> 278 : public __tuple_convertible_imp< 279 typename __make_tuple_types<_Tp>::type 280 , typename __make_tuple_types<_Up>::type 281 > 282 {}; 283 284 template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value, 285 bool = __tuple_like<_Up>::value> 286 struct __tuple_convertible 287 : public false_type {}; 288 289 template <class _Tp, class _Up> 290 struct __tuple_convertible<_Tp, _Up, true, true> 291 : public __tuple_convertible_apply<tuple_size<typename remove_reference<_Tp>::type>::value == 292 tuple_size<_Up>::value, _Tp, _Up> 293 {}; 294 295 // __tuple_constructible 296 297 template <class, class> 298 struct __tuple_constructible_imp : public false_type {}; 299 300 template <class _Tp0, class ..._Tp, class _Up0, class ..._Up> 301 struct __tuple_constructible_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > 302 : public integral_constant<bool, 303 is_constructible<_Up0, _Tp0>::value && 304 __tuple_constructible_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; 305 306 template <> 307 struct __tuple_constructible_imp<__tuple_types<>, __tuple_types<> > 308 : public true_type {}; 309 310 template <bool _SameSize, class, class> 311 struct __tuple_constructible_apply : public false_type {}; 312 313 template <class _Tp, class _Up> 314 struct __tuple_constructible_apply<true, _Tp, _Up> 315 : public __tuple_constructible_imp< 316 typename __make_tuple_types<_Tp>::type 317 , typename __make_tuple_types<_Up>::type 318 > 319 {}; 320 321 template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value, 322 bool = __tuple_like<_Up>::value> 323 struct __tuple_constructible 324 : public false_type {}; 325 326 template <class _Tp, class _Up> 327 struct __tuple_constructible<_Tp, _Up, true, true> 328 : public __tuple_constructible_apply<tuple_size<typename remove_reference<_Tp>::type>::value == 329 tuple_size<_Up>::value, _Tp, _Up> 330 {}; 331 332 // __tuple_assignable 333 334 template <class, class> 335 struct __tuple_assignable_imp : public false_type {}; 336 337 template <class _Tp0, class ..._Tp, class _Up0, class ..._Up> 338 struct __tuple_assignable_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > 339 : public integral_constant<bool, 340 is_assignable<_Up0&, _Tp0>::value && 341 __tuple_assignable_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; 342 343 template <> 344 struct __tuple_assignable_imp<__tuple_types<>, __tuple_types<> > 345 : public true_type {}; 346 347 template <bool, class, class> 348 struct __tuple_assignable_apply : public false_type {}; 349 350 template <class _Tp, class _Up> 351 struct __tuple_assignable_apply<true, _Tp, _Up> 352 : __tuple_assignable_imp< 353 typename __make_tuple_types<_Tp>::type 354 , typename __make_tuple_types<_Up>::type 355 > 356 {}; 357 358 template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value, 359 bool = __tuple_like<_Up>::value> 360 struct __tuple_assignable 361 : public false_type {}; 362 363 template <class _Tp, class _Up> 364 struct __tuple_assignable<_Tp, _Up, true, true> 365 : public __tuple_assignable_apply<tuple_size<typename remove_reference<_Tp>::type>::value == 366 tuple_size<_Up>::value, _Tp, _Up> 367 {}; 368 369 #endif // _LIBCPP_HAS_NO_VARIADICS 370 371 _LIBCPP_END_NAMESPACE_STD 372 373 #endif // _LIBCPP___TUPLE 374