[libcxx] r274330 - Flatten the tuple_element and __make_tuple_types implementations.
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 30 20:54:54 PDT 2016
Author: ericwf
Date: Thu Jun 30 22:54:54 2016
New Revision: 274330
URL: http://llvm.org/viewvc/llvm-project?rev=274330&view=rev
Log:
Flatten the tuple_element and __make_tuple_types implementations.
This patch attempts to improve the QoI of std::tuples tuple_element and
__make_tuple_types helpers. Previously they required O(N) instantiations,
one for every element in the tuple
The new implementations are O(1) after __tuple_indices<Id...> is created.
Added:
libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_element.fail.cpp
Modified:
libcxx/trunk/include/__tuple
Modified: libcxx/trunk/include/__tuple
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tuple?rev=274330&r1=274329&r2=274330&view=diff
==============================================================================
--- libcxx/trunk/include/__tuple (original)
+++ libcxx/trunk/include/__tuple Thu Jun 30 22:54:54 2016
@@ -228,26 +228,42 @@ get(const array<_Tp, _Size>&&) _NOEXCEPT
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)
-template <class _Hp, class ..._Tp>
-class _LIBCPP_TYPE_VIS_ONLY tuple_element<0, __tuple_types<_Hp, _Tp...> >
-{
-public:
- typedef _Hp type;
-};
+namespace __indexer_detail {
+
+template <size_t _Idx, class _Tp>
+struct __indexed { using type = _Tp; };
+
+template <class _Types, class _Indexes> struct __indexer;
+
+template <class ..._Types, size_t ..._Idx>
+struct __indexer<__tuple_types<_Types...>, __tuple_indices<_Idx...>>
+ : __indexed<_Idx, _Types>...
+{};
+
+template <size_t _Idx, class _Tp>
+__indexed<_Idx, _Tp> __at_index(__indexed<_Idx, _Tp> const&);
-template <size_t _Ip, class _Hp, class ..._Tp>
-class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, __tuple_types<_Hp, _Tp...> >
+} // namespace __indexer_detail
+
+template <size_t _Idx, class ..._Types>
+using __type_pack_element = typename decltype(
+ __indexer_detail::__at_index<_Idx>(
+ __indexer_detail::__indexer<
+ __tuple_types<_Types...>,
+ typename __make_tuple_indices<sizeof...(_Types)>::type
+ >{})
+ )::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;
+ static_assert(_Ip < sizeof...(_Types), "tuple_element index out of range");
+ typedef __type_pack_element<_Ip, _Types...> type;
};
template <class ..._Tp>
@@ -258,6 +274,46 @@ class _LIBCPP_TYPE_VIS_ONLY tuple_size<_
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
@@ -265,31 +321,47 @@ template <class... _Tp> struct __tuple_l
// _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>
+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 _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,
+ bool _SameSize = (_Ep == tuple_size<typename remove_reference<_Tp>::type>::value)>
+struct __make_tuple_types
{
- 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;
+ static_assert(_Sp <= _Ep, "__make_tuple_types input error");
+ 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, class _Tp, size_t _Ep>
-struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep>
-{
- typedef __tuple_types<_Types...> type;
+template <class ..._Types, size_t _Ep>
+struct __make_tuple_types<tuple<_Types...>, _Ep, 0, true> {
+ typedef __tuple_types<_Types...> type;
};
-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;
+template <class ..._Types, size_t _Ep>
+struct __make_tuple_types<__tuple_types<_Types...>, _Ep, 0, true> {
+ typedef __tuple_types<_Types...> type;
};
// __tuple_convertible
Added: libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_element.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_element.fail.cpp?rev=274330&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_element.fail.cpp (added)
+++ libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_element.fail.cpp Thu Jun 30 22:54:54 2016
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <tuple>
+
+// template <class... Types> class tuple;
+
+// template <size_t I, class... Types>
+// class tuple_element<I, tuple<Types...> >
+// {
+// public:
+// typedef Ti type;
+// };
+
+// UNSUPPORTED: c++98, c++03
+
+#include <tuple>
+#include <type_traits>
+
+int main()
+{
+ using T = std::tuple<int, long, void*>;
+ using E1 = typename std::tuple_element<1, T &>::type; // expected-error{{undefined template}}
+ using E2 = typename std::tuple_element<3, T>::type;
+ using E3 = typename std::tuple_element<4, T const>::type;
+ // expected-error at __tuple:* 2 {{static_assert failed}}
+
+}
More information about the cfe-commits
mailing list