Home | History | Annotate | Download | only in include
      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 
     30 template <class _Tp> class _LIBCPP_TYPE_VIS tuple_size;
     31 
     32 template <class _Tp>
     33 class _LIBCPP_TYPE_VIS tuple_size<const _Tp>
     34     : public tuple_size<_Tp> {};
     35 
     36 template <class _Tp>
     37 class _LIBCPP_TYPE_VIS tuple_size<volatile _Tp>
     38     : public tuple_size<_Tp> {};
     39 
     40 template <class _Tp>
     41 class _LIBCPP_TYPE_VIS tuple_size<const volatile _Tp>
     42     : public tuple_size<_Tp> {};
     43 
     44 template <size_t _Ip, class _Tp> class _LIBCPP_TYPE_VIS tuple_element;
     45 
     46 template <size_t _Ip, class _Tp>
     47 class _LIBCPP_TYPE_VIS tuple_element<_Ip, const _Tp>
     48 {
     49 public:
     50     typedef typename add_const<typename tuple_element<_Ip, _Tp>::type>::type type;
     51 };
     52 
     53 template <size_t _Ip, class _Tp>
     54 class _LIBCPP_TYPE_VIS tuple_element<_Ip, volatile _Tp>
     55 {
     56 public:
     57     typedef typename add_volatile<typename tuple_element<_Ip, _Tp>::type>::type type;
     58 };
     59 
     60 template <size_t _Ip, class _Tp>
     61 class _LIBCPP_TYPE_VIS tuple_element<_Ip, const volatile _Tp>
     62 {
     63 public:
     64     typedef typename add_cv<typename tuple_element<_Ip, _Tp>::type>::type type;
     65 };
     66 
     67 template <class ..._Tp> class _LIBCPP_TYPE_VIS tuple;
     68 template <class _T1, class _T2> struct _LIBCPP_TYPE_VIS pair;
     69 template <class _Tp, size_t _Size> struct _LIBCPP_TYPE_VIS array;
     70 
     71 template <class _Tp> struct __tuple_like : false_type {};
     72 
     73 template <class _Tp> struct __tuple_like<const _Tp> : public __tuple_like<_Tp> {};
     74 template <class _Tp> struct __tuple_like<volatile _Tp> : public __tuple_like<_Tp> {};
     75 template <class _Tp> struct __tuple_like<const volatile _Tp> : public __tuple_like<_Tp> {};
     76 
     77 template <class... _Tp> struct __tuple_like<tuple<_Tp...> > : true_type {};
     78 template <class _T1, class _T2> struct __tuple_like<pair<_T1, _T2> > : true_type {};
     79 template <class _Tp, size_t _Size> struct __tuple_like<array<_Tp, _Size> > : true_type {};
     80 
     81 template <size_t _Ip, class ..._Tp>
     82 _LIBCPP_INLINE_VISIBILITY
     83 typename tuple_element<_Ip, tuple<_Tp...> >::type&
     84 get(tuple<_Tp...>&) _NOEXCEPT;
     85 
     86 template <size_t _Ip, class ..._Tp>
     87 _LIBCPP_INLINE_VISIBILITY
     88 const typename tuple_element<_Ip, tuple<_Tp...> >::type&
     89 get(const tuple<_Tp...>&) _NOEXCEPT;
     90 
     91 template <size_t _Ip, class ..._Tp>
     92 _LIBCPP_INLINE_VISIBILITY
     93 typename tuple_element<_Ip, tuple<_Tp...> >::type&&
     94 get(tuple<_Tp...>&&) _NOEXCEPT;
     95 
     96 template <size_t _Ip, class _T1, class _T2>
     97 _LIBCPP_INLINE_VISIBILITY
     98 typename tuple_element<_Ip, pair<_T1, _T2> >::type&
     99 get(pair<_T1, _T2>&) _NOEXCEPT;
    100 
    101 template <size_t _Ip, class _T1, class _T2>
    102 _LIBCPP_INLINE_VISIBILITY
    103 const typename tuple_element<_Ip, pair<_T1, _T2> >::type&
    104 get(const pair<_T1, _T2>&) _NOEXCEPT;
    105 
    106 template <size_t _Ip, class _T1, class _T2>
    107 _LIBCPP_INLINE_VISIBILITY
    108 typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
    109 get(pair<_T1, _T2>&&) _NOEXCEPT;
    110 
    111 template <size_t _Ip, class _Tp, size_t _Size>
    112 _LIBCPP_INLINE_VISIBILITY
    113 _Tp&
    114 get(array<_Tp, _Size>&) _NOEXCEPT;
    115 
    116 template <size_t _Ip, class _Tp, size_t _Size>
    117 _LIBCPP_INLINE_VISIBILITY
    118 const _Tp&
    119 get(const array<_Tp, _Size>&) _NOEXCEPT;
    120 
    121 template <size_t _Ip, class _Tp, size_t _Size>
    122 _LIBCPP_INLINE_VISIBILITY
    123 _Tp&&
    124 get(array<_Tp, _Size>&&) _NOEXCEPT;
    125 
    126 // __make_tuple_indices
    127 
    128 template <size_t...> struct __tuple_indices {};
    129 
    130 template <size_t _Sp, class _IntTuple, size_t _Ep>
    131 struct __make_indices_imp;
    132 
    133 template <size_t _Sp, size_t ..._Indices, size_t _Ep>
    134 struct __make_indices_imp<_Sp, __tuple_indices<_Indices...>, _Ep>
    135 {
    136     typedef typename __make_indices_imp<_Sp+1, __tuple_indices<_Indices..., _Sp>, _Ep>::type type;
    137 };
    138 
    139 template <size_t _Ep, size_t ..._Indices>
    140 struct __make_indices_imp<_Ep, __tuple_indices<_Indices...>, _Ep>
    141 {
    142     typedef __tuple_indices<_Indices...> type;
    143 };
    144 
    145 template <size_t _Ep, size_t _Sp = 0>
    146 struct __make_tuple_indices
    147 {
    148     static_assert(_Sp <= _Ep, "__make_tuple_indices input error");
    149     typedef typename __make_indices_imp<_Sp, __tuple_indices<>, _Ep>::type type;
    150 };
    151 
    152 // __tuple_types
    153 
    154 template <class ..._Tp> struct __tuple_types {};
    155 
    156 template <size_t _Ip>
    157 class _LIBCPP_TYPE_VIS tuple_element<_Ip, __tuple_types<> >
    158 {
    159 public:
    160     static_assert(_Ip == 0, "tuple_element index out of range");
    161     static_assert(_Ip != 0, "tuple_element index out of range");
    162 };
    163 
    164 template <class _Hp, class ..._Tp>
    165 class _LIBCPP_TYPE_VIS tuple_element<0, __tuple_types<_Hp, _Tp...> >
    166 {
    167 public:
    168     typedef _Hp type;
    169 };
    170 
    171 template <size_t _Ip, class _Hp, class ..._Tp>
    172 class _LIBCPP_TYPE_VIS tuple_element<_Ip, __tuple_types<_Hp, _Tp...> >
    173 {
    174 public:
    175     typedef typename tuple_element<_Ip-1, __tuple_types<_Tp...> >::type type;
    176 };
    177 
    178 template <class ..._Tp>
    179 class _LIBCPP_TYPE_VIS tuple_size<__tuple_types<_Tp...> >
    180     : public integral_constant<size_t, sizeof...(_Tp)>
    181 {
    182 };
    183 
    184 template <class... _Tp> struct __tuple_like<__tuple_types<_Tp...> > : true_type {};
    185 
    186 // __make_tuple_types
    187 
    188 // __make_tuple_types<_Tuple<_Types...>, _Ep, _Sp>::type is a
    189 // __tuple_types<_Types...> using only those _Types in the range [_Sp, _Ep).
    190 // _Sp defaults to 0 and _Ep defaults to tuple_size<_Tuple>.  If _Tuple is a
    191 // lvalue_reference type, then __tuple_types<_Types&...> is the result.
    192 
    193 template <class _TupleTypes, class _Tp, size_t _Sp, size_t _Ep>
    194 struct __make_tuple_types_imp;
    195 
    196 template <class ..._Types, class _Tp, size_t _Sp, size_t _Ep>
    197 struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Sp, _Ep>
    198 {
    199     typedef typename remove_reference<_Tp>::type _Tpr;
    200     typedef typename __make_tuple_types_imp<__tuple_types<_Types...,
    201                                             typename conditional<is_lvalue_reference<_Tp>::value,
    202                                                 typename tuple_element<_Sp, _Tpr>::type&,
    203                                                 typename tuple_element<_Sp, _Tpr>::type>::type>,
    204                                             _Tp, _Sp+1, _Ep>::type type;
    205 };
    206 
    207 template <class ..._Types, class _Tp, size_t _Ep>
    208 struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep>
    209 {
    210     typedef __tuple_types<_Types...> type;
    211 };
    212 
    213 template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value, size_t _Sp = 0>
    214 struct __make_tuple_types
    215 {
    216     static_assert(_Sp <= _Ep, "__make_tuple_types input error");
    217     typedef typename __make_tuple_types_imp<__tuple_types<>, _Tp, _Sp, _Ep>::type type;
    218 };
    219 
    220 // __tuple_convertible
    221 
    222 template <bool, class _Tp, class _Up>
    223 struct __tuple_convertible_imp : public false_type {};
    224 
    225 template <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
    226 struct __tuple_convertible_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> >
    227     : public integral_constant<bool,
    228                                is_convertible<_Tp0, _Up0>::value &&
    229                                __tuple_convertible_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {};
    230 
    231 template <>
    232 struct __tuple_convertible_imp<true, __tuple_types<>, __tuple_types<> >
    233     : public true_type {};
    234 
    235 template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
    236                                 bool = __tuple_like<_Up>::value>
    237 struct __tuple_convertible
    238     : public false_type {};
    239 
    240 template <class _Tp, class _Up>
    241 struct __tuple_convertible<_Tp, _Up, true, true>
    242     : public __tuple_convertible_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==
    243                                      tuple_size<_Up>::value,
    244              typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type>
    245 {};
    246 
    247 // __tuple_constructible
    248 
    249 template <bool, class _Tp, class _Up>
    250 struct __tuple_constructible_imp : public false_type {};
    251 
    252 template <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
    253 struct __tuple_constructible_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> >
    254     : public integral_constant<bool,
    255                                is_constructible<_Up0, _Tp0>::value &&
    256                                __tuple_constructible_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {};
    257 
    258 template <>
    259 struct __tuple_constructible_imp<true, __tuple_types<>, __tuple_types<> >
    260     : public true_type {};
    261 
    262 template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
    263                                 bool = __tuple_like<_Up>::value>
    264 struct __tuple_constructible
    265     : public false_type {};
    266 
    267 template <class _Tp, class _Up>
    268 struct __tuple_constructible<_Tp, _Up, true, true>
    269     : public __tuple_constructible_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==
    270                                      tuple_size<_Up>::value,
    271              typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type>
    272 {};
    273 
    274 // __tuple_assignable
    275 
    276 template <bool, class _Tp, class _Up>
    277 struct __tuple_assignable_imp : public false_type {};
    278 
    279 template <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
    280 struct __tuple_assignable_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> >
    281     : public integral_constant<bool,
    282                                is_assignable<_Up0&, _Tp0>::value &&
    283                                __tuple_assignable_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {};
    284 
    285 template <>
    286 struct __tuple_assignable_imp<true, __tuple_types<>, __tuple_types<> >
    287     : public true_type {};
    288 
    289 template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
    290                                 bool = __tuple_like<_Up>::value>
    291 struct __tuple_assignable
    292     : public false_type {};
    293 
    294 template <class _Tp, class _Up>
    295 struct __tuple_assignable<_Tp, _Up, true, true>
    296     : public __tuple_assignable_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==
    297                                     tuple_size<_Up>::value,
    298              typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type>
    299 {};
    300 
    301 _LIBCPP_END_NAMESPACE_STD
    302 
    303 #endif  // _LIBCPP_HAS_NO_VARIADICS
    304 
    305 #endif  // _LIBCPP___TUPLE
    306