diff options
Diffstat (limited to 'libcxx/include/tuple')
-rw-r--r-- | libcxx/include/tuple | 203 |
1 files changed, 125 insertions, 78 deletions
diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 1623702..23a391d 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -106,6 +106,11 @@ public: void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...)); // constexpr in C++20 constexpr void swap(const tuple&) const noexcept(see-below); // C++23 + + template<tuple-like UTuple> + friend constexpr bool operator==(const tuple& t, const UTuple& u); // C++23 + template<tuple-like UTuple> + friend constexpr auto operator<=>(const tuple& t, const UTuple& u); // C++23 }; @@ -220,6 +225,7 @@ template <class... Types> # include <__config> # include <__cstddef/size_t.h> # include <__fwd/array.h> +# include <__fwd/get.h> # include <__fwd/pair.h> # include <__fwd/tuple.h> # include <__memory/allocator_arg_t.h> @@ -229,6 +235,7 @@ template <class... Types> # include <__tuple/make_tuple_types.h> # include <__tuple/sfinae_helpers.h> # include <__tuple/tuple_element.h> +# include <__tuple/tuple_like.h> # include <__tuple/tuple_like_ext.h> # include <__tuple/tuple_size.h> # include <__tuple/tuple_types.h> @@ -287,6 +294,68 @@ _LIBCPP_BEGIN_NAMESPACE_STD # ifndef _LIBCPP_CXX03_LANG +template <size_t _Ip, class _Tp, class _Up> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool __tuple_compare_equal(const _Tp& __x, const _Up& __y) { + if constexpr (_Ip == 0) + return true; + else + return std::__tuple_compare_equal<_Ip - 1>(__x, __y) && std::get<_Ip - 1>(__x) == std::get<_Ip - 1>(__y); +} + +# if _LIBCPP_STD_VER >= 26 +template <class _Tp, class _Up, class _IndexSeq = make_index_sequence<tuple_size_v<_Tp>>> +inline constexpr bool __can_tuple_compare_equal = false; + +// TODO(LLVM 22): Remove `tuple_size_v<_Tp> == tuple_size_v<_Up>` here once once LLVM-20 support ends +// because the resolution of CWG2369 landed in LLVM-21. +template <class _Tp, class _Up, size_t... _Is> + requires(tuple_size_v<_Tp> == tuple_size_v<_Up>) +inline constexpr bool __can_tuple_compare_equal<_Tp, _Up, index_sequence<_Is...>> = + __all<requires(const tuple_element_t<_Is, _Tp>& __t, const tuple_element_t<_Is, _Up>& __u) { + { __t == __u } -> __boolean_testable; + }...>::value; +# endif // _LIBCPP_STD_VER >= 26 + +# if _LIBCPP_STD_VER >= 20 +template <class _Ret, class _Tp, class _Up, size_t... _Is> +_LIBCPP_HIDE_FROM_ABI constexpr _Ret __tuple_compare_three_way(const _Tp& __x, const _Up& __y, index_sequence<_Is...>) { + _Ret __result = strong_ordering::equal; + static_cast<void>( + ((__result = std::__synth_three_way(std::get<_Is>(__x), std::get<_Is>(__y)), __result != 0) || ...)); + return __result; +} +# endif // _LIBCPP_STD_VER >= 20 + +# if _LIBCPP_STD_VER >= 23 +template <class> +inline constexpr bool __is_tuple_v = false; + +template <class... _Tp> +inline constexpr bool __is_tuple_v<tuple<_Tp...>> = true; + +template <class _Tp> +concept __tuple_like_no_tuple = __tuple_like<_Tp> && !__is_tuple_v<_Tp>; + +template <class _Tp, class _Up, class _IndexSeq> +struct __tuple_common_comparison_category_impl {}; + +// TODO(LLVM 22): Remove `tuple_size_v<_Tp> == tuple_size_v<_Up>` here once once LLVM-20 support ends +// because the resolution of CWG2369 landed in LLVM-21. +template <class _Tp, class _Up, size_t... _Is> + requires(tuple_size_v<_Tp> == tuple_size_v<_Up>) && requires { + typename common_comparison_category_t< + __synth_three_way_result<tuple_element_t<_Is, _Tp>, tuple_element_t<_Is, _Up>>...>; + } +struct __tuple_common_comparison_category_impl<_Tp, _Up, index_sequence<_Is...>> { + using type _LIBCPP_NODEBUG = + common_comparison_category_t<__synth_three_way_result<tuple_element_t<_Is, _Tp>, tuple_element_t<_Is, _Up>>...>; +}; + +template <__tuple_like _Tp, __tuple_like _Up> +using __tuple_common_comparison_category _LIBCPP_NODEBUG = + __tuple_common_comparison_category_impl<_Tp, _Up, make_index_sequence<tuple_size_v<_Tp>>>::type; +# endif // _LIBCPP_STD_VER >= 23 + // __tuple_leaf template <size_t _Ip, class _Hp, bool = is_empty<_Hp>::value && !__libcpp_is_final<_Hp>::value > @@ -448,33 +517,28 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __swallow(_Tp&&...) _NO template <class _Indx, class... _Tp> struct __tuple_impl; +struct __forward_args {}; +struct __value_init {}; + template <size_t... _Indx, class... _Tp> struct _LIBCPP_DECLSPEC_EMPTY_BASES __tuple_impl<__index_sequence<_Indx...>, _Tp...> : public __tuple_leaf<_Indx, _Tp>... { _LIBCPP_HIDE_FROM_ABI constexpr __tuple_impl() noexcept( __all<is_nothrow_default_constructible<_Tp>::value...>::value) {} - template <size_t... _Uf, class... _Tf, size_t... _Ul, class... _Tl, class... _Up> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_impl( - __index_sequence<_Uf...>, - __tuple_types<_Tf...>, - __index_sequence<_Ul...>, - __tuple_types<_Tl...>, - _Up&&... __u) noexcept(__all<is_nothrow_constructible<_Tf, _Up>::value...>::value && - __all<is_nothrow_default_constructible<_Tl>::value...>::value) - : __tuple_leaf<_Uf, _Tf>(std::forward<_Up>(__u))..., __tuple_leaf<_Ul, _Tl>()... {} - - template <class _Alloc, size_t... _Uf, class... _Tf, size_t... _Ul, class... _Tl, class... _Up> + template <class... _Args> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_impl(__forward_args, _Args&&... __args) + : __tuple_leaf<_Indx, _Tp>(std::forward<_Args>(__args))... {} + + template <class _Alloc> + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_impl(allocator_arg_t, const _Alloc& __alloc, __value_init) + : __tuple_leaf<_Indx, _Tp>(__uses_alloc_ctor<_Tp, _Alloc>(), __alloc)... {} + + template <class _Alloc, class... _Args> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_impl( - allocator_arg_t, - const _Alloc& __a, - __index_sequence<_Uf...>, - __tuple_types<_Tf...>, - __index_sequence<_Ul...>, - __tuple_types<_Tl...>, - _Up&&... __u) - : __tuple_leaf<_Uf, _Tf>(__uses_alloc_ctor<_Tf, _Alloc, _Up>(), __a, std::forward<_Up>(__u))..., - __tuple_leaf<_Ul, _Tl>(__uses_alloc_ctor<_Tl, _Alloc>(), __a)... {} + allocator_arg_t, const _Alloc& __alloc, __forward_args, _Args&&... __args) + : __tuple_leaf<_Indx, _Tp>(__uses_alloc_ctor<_Tp, _Alloc, _Args>(), __alloc, std::forward<_Args>(__args))... {} template <class _Tuple, __enable_if_t<__tuple_constructible<_Tuple, tuple<_Tp...> >::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_impl(_Tuple&& __t) noexcept( @@ -559,12 +623,7 @@ public: __enable_if_t< _And< _IsDefault<_Tp>... >::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, _IsImpDefault<_Tp>...> >::value) tuple(allocator_arg_t, _Alloc const& __a) - : __base_(allocator_arg_t(), - __a, - __index_sequence<>(), - __tuple_types<>(), - __make_index_sequence<sizeof...(_Tp)>(), - __tuple_types<_Tp...>()) {} + : __base_(allocator_arg_t(), __a, __value_init{}) {} // tuple(const T&...) constructors (including allocator_arg_t variants) template <template <class...> class _And = _And, @@ -572,11 +631,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<const _Tp&, _Tp>...> >::value) tuple(const _Tp&... __t) noexcept(_And<is_nothrow_copy_constructible<_Tp>...>::value) - : __base_(__make_index_sequence<sizeof...(_Tp)>(), - __tuple_types<_Tp...>(), - __index_sequence<>(), - __tuple_types<>(), - __t...) {} + : __base_(__forward_args{}, __t...) {} template <class _Alloc, template <class...> class _And = _And, @@ -584,13 +639,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, is_convertible<const _Tp&, _Tp>...> >::value) tuple(allocator_arg_t, const _Alloc& __a, const _Tp&... __t) - : __base_(allocator_arg_t(), - __a, - __make_index_sequence<sizeof...(_Tp)>(), - __tuple_types<_Tp...>(), - __index_sequence<>(), - __tuple_types<>(), - __t...) {} + : __base_(allocator_arg_t(), __a, __forward_args{}, __t...) {} // tuple(U&& ...) constructors (including allocator_arg_t variants) template <class... _Up> @@ -609,11 +658,7 @@ public: int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value) tuple(_Up&&... __u) noexcept(_And<is_nothrow_constructible<_Tp, _Up>...>::value) - : __base_(__make_index_sequence<sizeof...(_Up)>(), - __tuple_types<_Tp...>(), - __index_sequence<>(), - __tuple_types<>(), - std::forward<_Up>(__u)...) {} + : __base_(__forward_args{}, std::forward<_Up>(__u)...) {} template <class _Alloc, class... _Up, @@ -621,13 +666,7 @@ public: int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value) tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u) - : __base_(allocator_arg_t(), - __a, - __make_index_sequence<sizeof...(_Up)>(), - __tuple_types<_Tp...>(), - __index_sequence<>(), - __tuple_types<>(), - std::forward<_Up>(__u)...) {} + : __base_(allocator_arg_t(), __a, __forward_args{}, std::forward<_Up>(__u)...) {} // Copy and move constructors (including the allocator_arg_t variants) tuple(const tuple&) = default; @@ -986,7 +1025,24 @@ public: noexcept(__all<is_nothrow_swappable_v<const _Tp&>...>::value) { __base_.swap(__t.__base_); } -# endif // _LIBCPP_STD_VER >= 23 + + template <__tuple_like_no_tuple _UTuple> +# if _LIBCPP_STD_VER >= 26 + requires __can_tuple_compare_equal<tuple, _UTuple> && (sizeof...(_Tp) == tuple_size_v<_UTuple>) +# endif // _LIBCPP_STD_VER >= 26 + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const tuple& __x, const _UTuple& __y) { + static_assert(sizeof...(_Tp) == tuple_size_v<_UTuple>, "Can't compare tuple-like values of different sizes"); + return std::__tuple_compare_equal<sizeof...(_Tp)>(__x, __y); + } + + template <__tuple_like_no_tuple _UTuple> + requires(sizeof...(_Tp) == tuple_size_v<_UTuple>) + _LIBCPP_HIDE_FROM_ABI friend constexpr __tuple_common_comparison_category<tuple, _UTuple> + operator<=>(const tuple& __x, const _UTuple& __y) { + return std::__tuple_compare_three_way<__tuple_common_comparison_category<tuple, _UTuple>>( + __x, __y, index_sequence_for<_Tp...>{}); + } +# endif // _LIBCPP_STD_VER >= 23 }; _LIBCPP_DIAGNOSTIC_PUSH @@ -1008,6 +1064,21 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(tuple&) _NOEXCEPT {} # if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr void swap(const tuple&) const noexcept {} + + template <__tuple_like_no_tuple _UTuple> +# if _LIBCPP_STD_VER >= 26 + requires(tuple_size_v<_UTuple> == 0) +# endif // _LIBCPP_STD_VER >= 26 + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const tuple&, const _UTuple&) { + static_assert(tuple_size_v<_UTuple> == 0, "Can't compare tuple-like values of different sizes"); + return true; + } + + template <__tuple_like_no_tuple _UTuple> + requires(tuple_size_v<_UTuple> == 0) + _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering operator<=>(const tuple&, const _UTuple&) { + return strong_ordering::equal; + } # endif }; _LIBCPP_DIAGNOSTIC_POP @@ -1126,22 +1197,6 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<_Tp&&...> forwa return tuple<_Tp&&...>(std::forward<_Tp>(__t)...); } -template <size_t _Ip> -struct __tuple_equal { - template <class _Tp, class _Up> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _Tp& __x, const _Up& __y) { - return __tuple_equal<_Ip - 1>()(__x, __y) && std::get<_Ip - 1>(__x) == std::get<_Ip - 1>(__y); - } -}; - -template <> -struct __tuple_equal<0> { - template <class _Tp, class _Up> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _Tp&, const _Up&) { - return true; - } -}; - template <class... _Tp, class... _Up> # if _LIBCPP_STD_VER >= 26 requires(__all<requires(const _Tp& __t, const _Up& __u) { @@ -1151,27 +1206,19 @@ template <class... _Tp, class... _Up> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) { static_assert(sizeof...(_Tp) == sizeof...(_Up), "Can't compare tuples of different sizes"); - return __tuple_equal<sizeof...(_Tp)>()(__x, __y); + return std::__tuple_compare_equal<sizeof...(_Tp)>(__x, __y); } # if _LIBCPP_STD_VER >= 20 // operator<=> -template <class... _Tp, class... _Up, size_t... _Is> -_LIBCPP_HIDE_FROM_ABI constexpr auto -__tuple_compare_three_way(const tuple<_Tp...>& __x, const tuple<_Up...>& __y, index_sequence<_Is...>) { - common_comparison_category_t<__synth_three_way_result<_Tp, _Up>...> __result = strong_ordering::equal; - static_cast<void>( - ((__result = std::__synth_three_way(std::get<_Is>(__x), std::get<_Is>(__y)), __result != 0) || ...)); - return __result; -} - template <class... _Tp, class... _Up> requires(sizeof...(_Tp) == sizeof...(_Up)) _LIBCPP_HIDE_FROM_ABI constexpr common_comparison_category_t<__synth_three_way_result<_Tp, _Up>...> operator<=>(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) { - return std::__tuple_compare_three_way(__x, __y, index_sequence_for<_Tp...>{}); + return std::__tuple_compare_three_way<common_comparison_category_t<__synth_three_way_result<_Tp, _Up>...>>( + __x, __y, index_sequence_for<_Tp...>{}); } # else // _LIBCPP_STD_VER >= 20 |