Flatten tuple_constructible, tuple_convertible and tuple_assignable.
This patch is the last in a series that replaces recursive meta-programming in std::tuple with non-recursive implementations. Previously std::tuple could only be instantiated with 126 elements before it blew the max template instantiation depth. Now the size of std::tuple is essentially unbounded (I've tested with over 5000 elements). One unfortunate side-effect of this change is that tuple_constructible and similar no longer short circuit after the first failure. Instead they evaluate the conditions for all elements. This could be potentially breaking. I plan to look into this further. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@274331 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
117
include/__tuple
117
include/__tuple
@@ -255,7 +255,6 @@ using __type_pack_element = typename decltype(
|
|||||||
typename __make_tuple_indices<sizeof...(_Types)>::type
|
typename __make_tuple_indices<sizeof...(_Types)>::type
|
||||||
>{})
|
>{})
|
||||||
)::type;
|
)::type;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <size_t _Ip, class ..._Types>
|
template <size_t _Ip, class ..._Types>
|
||||||
@@ -266,6 +265,7 @@ public:
|
|||||||
typedef __type_pack_element<_Ip, _Types...> type;
|
typedef __type_pack_element<_Ip, _Types...> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <class ..._Tp>
|
template <class ..._Tp>
|
||||||
class _LIBCPP_TYPE_VIS_ONLY tuple_size<__tuple_types<_Tp...> >
|
class _LIBCPP_TYPE_VIS_ONLY tuple_size<__tuple_types<_Tp...> >
|
||||||
: public integral_constant<size_t, sizeof...(_Tp)>
|
: public integral_constant<size_t, sizeof...(_Tp)>
|
||||||
@@ -364,32 +364,37 @@ struct __make_tuple_types<__tuple_types<_Types...>, _Ep, 0, true> {
|
|||||||
typedef __tuple_types<_Types...> type;
|
typedef __tuple_types<_Types...> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <bool ..._Preds>
|
||||||
|
struct __all_dummy;
|
||||||
|
|
||||||
|
template <bool ..._Pred>
|
||||||
|
using __all = is_same<__all_dummy<_Pred...>, __all_dummy<(_Pred, true)...>>;
|
||||||
|
|
||||||
|
struct __tuple_sfinae_base {
|
||||||
|
template <class ..._FromArgs, class ..._ToArgs>
|
||||||
|
static auto __test_constructible(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>)
|
||||||
|
-> __all<is_constructible<_ToArgs, _FromArgs>::value...>;
|
||||||
|
static auto __test_constructible(...) -> false_type;
|
||||||
|
template <class _Types1, class _Types2>
|
||||||
|
using __constructible = decltype(__test_constructible(_Types1{}, _Types2{}));
|
||||||
|
|
||||||
|
template <class ..._FromArgs, class ..._ToArgs>
|
||||||
|
static auto __test_convertible(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>)
|
||||||
|
-> __all<is_convertible<_FromArgs, _ToArgs>::value...>;
|
||||||
|
static auto __test_convertible(...) -> false_type;
|
||||||
|
template <class _Types1, class _Types2>
|
||||||
|
using __convertible = decltype(__test_convertible(_Types1{}, _Types2{}));
|
||||||
|
|
||||||
|
template <class ..._FromArgs, class ..._ToArgs>
|
||||||
|
static auto __test_assignable(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>)
|
||||||
|
-> __all<is_assignable<_ToArgs&, _FromArgs>::value...>;
|
||||||
|
static auto __test_assignable(...) -> false_type;
|
||||||
|
template <class _Types1, class _Types2>
|
||||||
|
using __assignable = decltype(__test_assignable(_Types1{}, _Types2{}));
|
||||||
|
};
|
||||||
|
|
||||||
// __tuple_convertible
|
// __tuple_convertible
|
||||||
|
|
||||||
template <class, class>
|
|
||||||
struct __tuple_convertible_imp : public false_type {};
|
|
||||||
|
|
||||||
template <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
|
|
||||||
struct __tuple_convertible_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> >
|
|
||||||
: public integral_constant<bool,
|
|
||||||
is_convertible<_Tp0, _Up0>::value &&
|
|
||||||
__tuple_convertible_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct __tuple_convertible_imp<__tuple_types<>, __tuple_types<> >
|
|
||||||
: public true_type {};
|
|
||||||
|
|
||||||
template <bool, class, class>
|
|
||||||
struct __tuple_convertible_apply : public false_type {};
|
|
||||||
|
|
||||||
template <class _Tp, class _Up>
|
|
||||||
struct __tuple_convertible_apply<true, _Tp, _Up>
|
|
||||||
: public __tuple_convertible_imp<
|
|
||||||
typename __make_tuple_types<_Tp>::type
|
|
||||||
, typename __make_tuple_types<_Up>::type
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
|
template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
|
||||||
bool = __tuple_like<_Up>::value>
|
bool = __tuple_like<_Up>::value>
|
||||||
struct __tuple_convertible
|
struct __tuple_convertible
|
||||||
@@ -397,36 +402,14 @@ struct __tuple_convertible
|
|||||||
|
|
||||||
template <class _Tp, class _Up>
|
template <class _Tp, class _Up>
|
||||||
struct __tuple_convertible<_Tp, _Up, true, true>
|
struct __tuple_convertible<_Tp, _Up, true, true>
|
||||||
: public __tuple_convertible_apply<tuple_size<typename remove_reference<_Tp>::type>::value ==
|
: public __tuple_sfinae_base::__convertible<
|
||||||
tuple_size<_Up>::value, _Tp, _Up>
|
|
||||||
{};
|
|
||||||
|
|
||||||
// __tuple_constructible
|
|
||||||
|
|
||||||
template <class, class>
|
|
||||||
struct __tuple_constructible_imp : public false_type {};
|
|
||||||
|
|
||||||
template <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
|
|
||||||
struct __tuple_constructible_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> >
|
|
||||||
: public integral_constant<bool,
|
|
||||||
is_constructible<_Up0, _Tp0>::value &&
|
|
||||||
__tuple_constructible_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct __tuple_constructible_imp<__tuple_types<>, __tuple_types<> >
|
|
||||||
: public true_type {};
|
|
||||||
|
|
||||||
template <bool _SameSize, class, class>
|
|
||||||
struct __tuple_constructible_apply : public false_type {};
|
|
||||||
|
|
||||||
template <class _Tp, class _Up>
|
|
||||||
struct __tuple_constructible_apply<true, _Tp, _Up>
|
|
||||||
: public __tuple_constructible_imp<
|
|
||||||
typename __make_tuple_types<_Tp>::type
|
typename __make_tuple_types<_Tp>::type
|
||||||
, typename __make_tuple_types<_Up>::type
|
, typename __make_tuple_types<_Up>::type
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
// __tuple_constructible
|
||||||
|
|
||||||
template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
|
template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
|
||||||
bool = __tuple_like<_Up>::value>
|
bool = __tuple_like<_Up>::value>
|
||||||
struct __tuple_constructible
|
struct __tuple_constructible
|
||||||
@@ -434,36 +417,14 @@ struct __tuple_constructible
|
|||||||
|
|
||||||
template <class _Tp, class _Up>
|
template <class _Tp, class _Up>
|
||||||
struct __tuple_constructible<_Tp, _Up, true, true>
|
struct __tuple_constructible<_Tp, _Up, true, true>
|
||||||
: public __tuple_constructible_apply<tuple_size<typename remove_reference<_Tp>::type>::value ==
|
: public __tuple_sfinae_base::__constructible<
|
||||||
tuple_size<_Up>::value, _Tp, _Up>
|
|
||||||
{};
|
|
||||||
|
|
||||||
// __tuple_assignable
|
|
||||||
|
|
||||||
template <class, class>
|
|
||||||
struct __tuple_assignable_imp : public false_type {};
|
|
||||||
|
|
||||||
template <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
|
|
||||||
struct __tuple_assignable_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> >
|
|
||||||
: public integral_constant<bool,
|
|
||||||
is_assignable<_Up0&, _Tp0>::value &&
|
|
||||||
__tuple_assignable_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct __tuple_assignable_imp<__tuple_types<>, __tuple_types<> >
|
|
||||||
: public true_type {};
|
|
||||||
|
|
||||||
template <bool, class, class>
|
|
||||||
struct __tuple_assignable_apply : public false_type {};
|
|
||||||
|
|
||||||
template <class _Tp, class _Up>
|
|
||||||
struct __tuple_assignable_apply<true, _Tp, _Up>
|
|
||||||
: __tuple_assignable_imp<
|
|
||||||
typename __make_tuple_types<_Tp>::type
|
typename __make_tuple_types<_Tp>::type
|
||||||
, typename __make_tuple_types<_Up>::type
|
, typename __make_tuple_types<_Up>::type
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
// __tuple_assignable
|
||||||
|
|
||||||
template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
|
template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
|
||||||
bool = __tuple_like<_Up>::value>
|
bool = __tuple_like<_Up>::value>
|
||||||
struct __tuple_assignable
|
struct __tuple_assignable
|
||||||
@@ -471,8 +432,10 @@ struct __tuple_assignable
|
|||||||
|
|
||||||
template <class _Tp, class _Up>
|
template <class _Tp, class _Up>
|
||||||
struct __tuple_assignable<_Tp, _Up, true, true>
|
struct __tuple_assignable<_Tp, _Up, true, true>
|
||||||
: public __tuple_assignable_apply<tuple_size<typename remove_reference<_Tp>::type>::value ==
|
: public __tuple_sfinae_base::__assignable<
|
||||||
tuple_size<_Up>::value, _Tp, _Up>
|
typename __make_tuple_types<_Tp>::type
|
||||||
|
, typename __make_tuple_types<_Up>::type
|
||||||
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||||
|
|||||||
@@ -379,11 +379,6 @@ template <class ..._Tp>
|
|||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
void __swallow(_Tp&&...) _NOEXCEPT {}
|
void __swallow(_Tp&&...) _NOEXCEPT {}
|
||||||
|
|
||||||
template <bool ..._Pred>
|
|
||||||
struct __all
|
|
||||||
: is_same<__all<_Pred...>, __all<(_Pred, true)...>>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template <class ..._Tp>
|
template <class ..._Tp>
|
||||||
struct __lazy_all : __all<_Tp::value...> {};
|
struct __lazy_all : __all<_Tp::value...> {};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user