[libcxx] r274286 - Replace __make_tuple_indices implementation with superior implementation.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 30 15:34:43 PDT 2016


Author: ericwf
Date: Thu Jun 30 17:34:43 2016
New Revision: 274286

URL: http://llvm.org/viewvc/llvm-project?rev=274286&view=rev
Log:
Replace __make_tuple_indices implementation with superior implementation.

The previous __make_tuple_indices implementation caused O(N) instantiations
and was pretty inefficient. The C++14 __make_integer_sequence implementation
is much better, since it either uses a builtin to generate the sequence or
a very nice Log8(N) implementation provided by richard smith.

This patch moves the __make_integer_sequence implementation into __tuple
and uses it to implement __make_tuple_indices.

Since libc++ can't expose the name 'integer_sequence' in C++11 this patch
also introduces a dummy type '__integer_sequence' which is used when generating
the sequence. One the sequence is generated '__integer_sequence' can be
converted into the required type; either '__tuple_indices' or 'integer_sequence'.

Modified:
    libcxx/trunk/include/__tuple
    libcxx/trunk/include/utility

Modified: libcxx/trunk/include/__tuple
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tuple?rev=274286&r1=274285&r2=274286&view=diff
==============================================================================
--- libcxx/trunk/include/__tuple (original)
+++ libcxx/trunk/include/__tuple Thu Jun 30 17:34:43 2016
@@ -68,6 +68,80 @@ template <class _Tp> struct __tuple_like
 // tuple specializations
 
 #if !defined(_LIBCPP_HAS_NO_VARIADICS)
+
+template <size_t...> struct __tuple_indices {};
+
+template <class _IdxType, _IdxType... _Values>
+struct __integer_sequence {
+  template <template <class _OIdxType, _OIdxType...> class _ToIndexSeq, class _ToIndexType>
+  using __convert = _ToIndexSeq<_ToIndexType, _Values...>;
+
+  template <size_t _Sp>
+  using __to_tuple_indices = __tuple_indices<(_Values + _Sp)...>;
+};
+
+#if !__has_builtin(__make_integer_seq) || defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE)
+namespace __detail {
+
+template<typename _Tp, size_t ..._Extra> struct __repeat;
+template<typename _Tp, _Tp ..._Np, size_t ..._Extra> struct __repeat<__integer_sequence<_Tp, _Np...>, _Extra...> {
+  typedef __integer_sequence<_Tp,
+                           _Np...,
+                           sizeof...(_Np) + _Np...,
+                           2 * sizeof...(_Np) + _Np...,
+                           3 * sizeof...(_Np) + _Np...,
+                           4 * sizeof...(_Np) + _Np...,
+                           5 * sizeof...(_Np) + _Np...,
+                           6 * sizeof...(_Np) + _Np...,
+                           7 * sizeof...(_Np) + _Np...,
+                           _Extra...> type;
+};
+
+template<size_t _Np> struct __parity;
+template<size_t _Np> struct __make : __parity<_Np % 8>::template __pmake<_Np> {};
+
+template<> struct __make<0> { typedef __integer_sequence<size_t> type; };
+template<> struct __make<1> { typedef __integer_sequence<size_t, 0> type; };
+template<> struct __make<2> { typedef __integer_sequence<size_t, 0, 1> type; };
+template<> struct __make<3> { typedef __integer_sequence<size_t, 0, 1, 2> type; };
+template<> struct __make<4> { typedef __integer_sequence<size_t, 0, 1, 2, 3> type; };
+template<> struct __make<5> { typedef __integer_sequence<size_t, 0, 1, 2, 3, 4> type; };
+template<> struct __make<6> { typedef __integer_sequence<size_t, 0, 1, 2, 3, 4, 5> type; };
+template<> struct __make<7> { typedef __integer_sequence<size_t, 0, 1, 2, 3, 4, 5, 6> type; };
+
+template<> struct __parity<0> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type> {}; };
+template<> struct __parity<1> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 1> {}; };
+template<> struct __parity<2> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 2, _Np - 1> {}; };
+template<> struct __parity<3> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 3, _Np - 2, _Np - 1> {}; };
+template<> struct __parity<4> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
+template<> struct __parity<5> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
+template<> struct __parity<6> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
+template<> struct __parity<7> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 7, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
+
+} // namespace detail
+
+#endif  // !__has_builtin(__make_integer_seq) || defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE)
+
+#if __has_builtin(__make_integer_seq)
+template <size_t _Ep, size_t _Sp>
+using __make_indices_imp =
+    typename __make_integer_seq<__integer_sequence, size_t, _Ep - _Sp>::template
+    __to_tuple_indices<_Sp>;
+#else
+template <size_t _Ep, size_t _Sp>
+using __make_indices_imp =
+    typename __detail::__make<_Ep - _Sp>::type::template __to_tuple_indices<_Sp>;
+
+#endif
+
+template <size_t _Ep, size_t _Sp = 0>
+struct __make_tuple_indices
+{
+    static_assert(_Sp <= _Ep, "__make_tuple_indices input error");
+    typedef __make_indices_imp<_Ep, _Sp> type;
+};
+
+
 template <class ..._Tp> class _LIBCPP_TYPE_VIS_ONLY tuple;
 
 template <class... _Tp> struct __tuple_like<tuple<_Tp...> > : true_type {};
@@ -149,31 +223,6 @@ get(const array<_Tp, _Size>&&) _NOEXCEPT
 
 #if !defined(_LIBCPP_HAS_NO_VARIADICS)
 
-// __make_tuple_indices
-
-template <size_t...> struct __tuple_indices {};
-
-template <size_t _Sp, class _IntTuple, size_t _Ep>
-struct __make_indices_imp;
-
-template <size_t _Sp, size_t ..._Indices, size_t _Ep>
-struct __make_indices_imp<_Sp, __tuple_indices<_Indices...>, _Ep>
-{
-    typedef typename __make_indices_imp<_Sp+1, __tuple_indices<_Indices..., _Sp>, _Ep>::type type;
-};
-
-template <size_t _Ep, size_t ..._Indices>
-struct __make_indices_imp<_Ep, __tuple_indices<_Indices...>, _Ep>
-{
-    typedef __tuple_indices<_Indices...> type;
-};
-
-template <size_t _Ep, size_t _Sp = 0>
-struct __make_tuple_indices
-{
-    static_assert(_Sp <= _Ep, "__make_tuple_indices input error");
-    typedef typename __make_indices_imp<_Sp, __tuple_indices<>, _Ep>::type type;
-};
 
 // __tuple_types
 

Modified: libcxx/trunk/include/utility
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?rev=274286&r1=274285&r2=274286&view=diff
==============================================================================
--- libcxx/trunk/include/utility (original)
+++ libcxx/trunk/include/utility Thu Jun 30 17:34:43 2016
@@ -741,63 +741,15 @@ template<size_t... _Ip>
 #if __has_builtin(__make_integer_seq) && !defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE)
 
 template <class _Tp, _Tp _Ep>
-struct __make_integer_sequence
-{
-    typedef __make_integer_seq<integer_sequence, _Tp, _Ep> type;
-};
+using __make_integer_sequence = __make_integer_seq<integer_sequence, _Tp, _Ep>;
 
 #else
 
-namespace __detail {
-
-template<typename _Tp, size_t ..._Extra> struct __repeat;
-template<typename _Tp, _Tp ..._Np, size_t ..._Extra> struct __repeat<integer_sequence<_Tp, _Np...>, _Extra...> {
-  typedef integer_sequence<_Tp,
-                           _Np...,
-                           sizeof...(_Np) + _Np...,
-                           2 * sizeof...(_Np) + _Np...,
-                           3 * sizeof...(_Np) + _Np...,
-                           4 * sizeof...(_Np) + _Np...,
-                           5 * sizeof...(_Np) + _Np...,
-                           6 * sizeof...(_Np) + _Np...,
-                           7 * sizeof...(_Np) + _Np...,
-                           _Extra...> type;
-};
-
-template<size_t _Np> struct __parity;
-template<size_t _Np> struct __make : __parity<_Np % 8>::template __pmake<_Np> {};
-
-template<> struct __make<0> { typedef integer_sequence<size_t> type; };
-template<> struct __make<1> { typedef integer_sequence<size_t, 0> type; };
-template<> struct __make<2> { typedef integer_sequence<size_t, 0, 1> type; };
-template<> struct __make<3> { typedef integer_sequence<size_t, 0, 1, 2> type; };
-template<> struct __make<4> { typedef integer_sequence<size_t, 0, 1, 2, 3> type; };
-template<> struct __make<5> { typedef integer_sequence<size_t, 0, 1, 2, 3, 4> type; };
-template<> struct __make<6> { typedef integer_sequence<size_t, 0, 1, 2, 3, 4, 5> type; };
-template<> struct __make<7> { typedef integer_sequence<size_t, 0, 1, 2, 3, 4, 5, 6> type; };
-
-template<> struct __parity<0> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type> {}; };
-template<> struct __parity<1> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 1> {}; };
-template<> struct __parity<2> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 2, _Np - 1> {}; };
-template<> struct __parity<3> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 3, _Np - 2, _Np - 1> {}; };
-template<> struct __parity<4> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
-template<> struct __parity<5> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
-template<> struct __parity<6> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
-template<> struct __parity<7> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 7, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
-
-template<typename _Tp, typename _Up> struct __convert {
-  template<typename> struct __result;
-  template<_Tp ..._Np> struct __result<integer_sequence<_Tp, _Np...> > { typedef integer_sequence<_Up, _Np...> type; };
-};
-template<typename _Tp> struct __convert<_Tp, _Tp> { template<typename _Up> struct __result { typedef _Up type; }; };
-
-}
-
 template<typename _Tp, _Tp _Np> using __make_integer_sequence_unchecked =
-  typename __detail::__convert<size_t, _Tp>::template __result<typename __detail::__make<_Np>::type>::type;
+  typename __detail::__make<_Np>::type::template __convert<integer_sequence, _Tp>;
 
 template <class _Tp, _Tp _Ep>
-struct __make_integer_sequence
+struct __make_integer_sequence_checked
 {
     static_assert(is_integral<_Tp>::value,
                   "std::make_integer_sequence can only be instantiated with an integral type" );
@@ -807,10 +759,13 @@ struct __make_integer_sequence
     typedef __make_integer_sequence_unchecked<_Tp, 0 <= _Ep ? _Ep : 0> type;
 };
 
+template <class _Tp, _Tp _Ep>
+using __make_integer_sequence = typename __make_integer_sequence_checked<_Tp, _Ep>::type;
+
 #endif
 
 template<class _Tp, _Tp _Np>
-    using make_integer_sequence = typename __make_integer_sequence<_Tp, _Np>::type;
+    using make_integer_sequence = __make_integer_sequence<_Tp, _Np>;
 
 template<size_t _Np>
     using make_index_sequence = make_integer_sequence<size_t, _Np>;




More information about the cfe-commits mailing list