EricWF created this revision.
EricWF added a subscriber: cfe-commits.

http://reviews.llvm.org/D21918

Files:
  include/__tuple

Index: include/__tuple
===================================================================
--- include/__tuple
+++ include/__tuple
@@ -228,68 +228,141 @@
 
 template <class ..._Tp> struct __tuple_types {};
 
-template <size_t _Ip>
-class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, __tuple_types<> >
-{
-public:
-    static_assert(_Ip == 0, "tuple_element index out of range");
-    static_assert(_Ip != 0, "tuple_element index out of range");
-};
+#if !__has_builtin(__type_pack_element)
+namespace __indexer_detail {
+
+template <size_t _Idx, class _Tp>
+struct __indexed { using type = _Tp; };
+
+template <class _Types, class _Indexes> struct __indexer;
 
-template <class _Hp, class ..._Tp>
-class _LIBCPP_TYPE_VIS_ONLY tuple_element<0, __tuple_types<_Hp, _Tp...> >
+template <class ..._Types, size_t ..._Idx>
+struct __indexer<__tuple_types<_Types...>, __tuple_indices<_Idx...>>
+    : __indexed<_Idx, _Types>...
 {
-public:
-    typedef _Hp type;
 };
 
-template <size_t _Ip, class _Hp, class ..._Tp>
-class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, __tuple_types<_Hp, _Tp...> >
+template <class ..._Types>
+using __make_indexer = __indexer<__tuple_types<_Types...>,
+    typename __make_tuple_indices<sizeof...(_Types)>::type>;
+
+__nat __at_index(...);
+
+template <size_t _Idx, class _Tp>
+ __indexed<_Idx, _Tp> __at_index(__indexed<_Idx, _Tp> const&);
+
+} // namespace __indexer_detail
+
+template <size_t _Idx, class ..._Types>
+using __type_pack_element = typename decltype(
+    __indexer_detail::__at_index<_Idx>(
+        __indexer_detail::__make_indexer<_Types...>{}))::type;
+
+#endif
+
+template <size_t _Ip, class ..._Types>
+class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, __tuple_types<_Types...>>
 {
 public:
-    typedef typename tuple_element<_Ip-1, __tuple_types<_Tp...> >::type type;
+    typedef __type_pack_element<_Ip, _Types...> type;
 };
 
+
 template <class ..._Tp>
 class _LIBCPP_TYPE_VIS_ONLY tuple_size<__tuple_types<_Tp...> >
     : public integral_constant<size_t, sizeof...(_Tp)>
 {
 };
 
 template <class... _Tp> struct __tuple_like<__tuple_types<_Tp...> > : true_type {};
 
+template <bool _ApplyLV, bool _ApplyConst, bool _ApplyVolatile>
+struct __apply_cv_mf;
+template <>
+struct __apply_cv_mf<false, false, false> {
+  template <class _Tp> using __apply = _Tp;
+};
+template <>
+struct __apply_cv_mf<false, true, false> {
+  template <class _Tp> using __apply = const _Tp;
+};
+template <>
+struct __apply_cv_mf<false, false, true> {
+  template <class _Tp> using __apply = volatile _Tp;
+};
+template <>
+struct __apply_cv_mf<false, true, true> {
+  template <class _Tp> using __apply = const volatile _Tp;
+};
+template <>
+struct __apply_cv_mf<true, false, false> {
+  template <class _Tp> using __apply = _Tp&;
+};
+template <>
+struct __apply_cv_mf<true, true, false> {
+  template <class _Tp> using __apply = const _Tp&;
+};
+template <>
+struct __apply_cv_mf<true, false, true> {
+  template <class _Tp> using __apply = volatile _Tp&;
+};
+template <>
+struct __apply_cv_mf<true, true, true> {
+  template <class _Tp> using __apply = const volatile _Tp&;
+};
+template <class _Tp, class _RawTp = typename remove_reference<_Tp>::type>
+using __apply_cv_t = __apply_cv_mf<
+    is_lvalue_reference<_Tp>::value,
+    is_const<_RawTp>::value,
+    is_volatile<_RawTp>::value>;
+
 // __make_tuple_types
 
 // __make_tuple_types<_Tuple<_Types...>, _Ep, _Sp>::type is a
 // __tuple_types<_Types...> using only those _Types in the range [_Sp, _Ep).
 // _Sp defaults to 0 and _Ep defaults to tuple_size<_Tuple>.  If _Tuple is a
 // lvalue_reference type, then __tuple_types<_Types&...> is the result.
 
-template <class _TupleTypes, class _Tp, size_t _Sp, size_t _Ep>
-struct __make_tuple_types_imp;
+template <class _TupleTypes, class _TupleIndices>
+struct __make_tuple_types_flat;
 
-template <class ..._Types, class _Tp, size_t _Sp, size_t _Ep>
-struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Sp, _Ep>
-{
-    typedef typename remove_reference<_Tp>::type _Tpr;
-    typedef typename __make_tuple_types_imp<__tuple_types<_Types...,
-                                            typename conditional<is_lvalue_reference<_Tp>::value,
-                                                typename tuple_element<_Sp, _Tpr>::type&,
-                                                typename tuple_element<_Sp, _Tpr>::type>::type>,
-                                            _Tp, _Sp+1, _Ep>::type type;
+template <template <class...> class _Tuple, class ..._Types, size_t ..._Idx>
+struct __make_tuple_types_flat<_Tuple<_Types...>, __tuple_indices<_Idx...>> {
+  // Specialization for pair, tuple, and __tuple_types
+  template <class _Tp, class _ApplyFn = __apply_cv_t<_Tp>>
+  using __apply_quals = __tuple_types<
+      typename _ApplyFn::template __apply<__type_pack_element<_Idx, _Types...>>...
+    >;
 };
 
-template <class ..._Types, class _Tp, size_t _Ep>
-struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep>
-{
-    typedef __tuple_types<_Types...> type;
+template <class _Vt, size_t _Np, size_t ..._Idx>
+struct __make_tuple_types_flat<array<_Vt, _Np>, __tuple_indices<_Idx...>> {
+  using _Array = array<_Vt, _Np>;
+
+  template <class _Tp, class _ApplyFn = __apply_cv_t<_Tp>>
+  using __apply_quals = __tuple_types<
+      typename _ApplyFn::template __apply<typename tuple_element<_Idx, _Array>::type>...
+    >;
 };
 
-template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value, size_t _Sp = 0>
+template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value,
+          size_t _Sp = 0>
 struct __make_tuple_types
 {
     static_assert(_Sp <= _Ep, "__make_tuple_types input error");
-    typedef typename __make_tuple_types_imp<__tuple_types<>, _Tp, _Sp, _Ep>::type type;
+    using _RawTp = typename remove_cv<typename remove_reference<_Tp>::type>::type;
+    using _Maker = __make_tuple_types_flat<_RawTp, typename __make_tuple_indices<_Ep, _Sp>::type>;
+    using type = typename _Maker::template __apply_quals<_Tp>;
+};
+
+template <class ..._Types>
+struct __make_tuple_types<tuple<_Types...>, sizeof...(_Types), 0> {
+  typedef __tuple_types<_Types...> type;
+};
+
+template <class ..._Types>
+struct __make_tuple_types<__tuple_types<_Types...>, sizeof...(_Types), 0> {
+  typedef __tuple_types<_Types...> type;
 };
 
 // __tuple_convertible
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to